├── .gitignore ├── graphics ├── homekit.png ├── ustawienia.png ├── envoy_topbar.png └── homebridge-enphase-envoy.png ├── .github └── workflows │ └── stale.yml ├── LICENSE ├── src ├── impulsegenerator.js ├── digestauth.js ├── passwdcalc.js ├── envoytoken.js ├── mqtt.js ├── restful.js ├── functions.js └── constants.js ├── package.json ├── index.js ├── enphase_envoy.15s.rb ├── sample-config.json ├── README.md └── CHANGELOG.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /graphics/homekit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grzegorz914/homebridge-enphase-envoy/HEAD/graphics/homekit.png -------------------------------------------------------------------------------- /graphics/ustawienia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grzegorz914/homebridge-enphase-envoy/HEAD/graphics/ustawienia.png -------------------------------------------------------------------------------- /graphics/envoy_topbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grzegorz914/homebridge-enphase-envoy/HEAD/graphics/envoy_topbar.png -------------------------------------------------------------------------------- /graphics/homebridge-enphase-envoy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grzegorz914/homebridge-enphase-envoy/HEAD/graphics/homebridge-enphase-envoy.png -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Mark stale issues and pull requests 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' # Runs daily at midnight (UTC) 6 | workflow_dispatch: # Allows you to manually trigger the workflow 7 | 8 | jobs: 9 | stale: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/stale@v8 13 | with: 14 | repo-token: ${{ secrets.GITHUB_TOKEN }} 15 | stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.' 16 | days-before-stale: 30 17 | days-before-close: 7 18 | stale-pr-message: 'This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.' 19 | stale-issue-label: 'stale' 20 | exempt-issue-labels: 'pinned,security' 21 | close-issue-message: 'Closing this issue due to inactivity.' 22 | close-pr-message: 'Closing this pull request due to inactivity.' 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2022 Grzegorz Kaczor 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 | -------------------------------------------------------------------------------- /src/impulsegenerator.js: -------------------------------------------------------------------------------- 1 | import EventEmitter from 'events'; 2 | 3 | class ImpulseGenerator extends EventEmitter { 4 | constructor() { 5 | super(); 6 | this.timersState = false; 7 | this.timers = []; 8 | } 9 | 10 | async state(state, timers = [], runOnStart = true) { 11 | // Stop current timers before new start 12 | if (this.timersState && state) { 13 | await this.state(false); 14 | } 15 | 16 | if (state) { 17 | if (!Array.isArray(timers)) throw new Error('Timers must be an array'); 18 | 19 | for (const { name, sampling } of timers) { 20 | if (!name || !sampling) continue; 21 | 22 | if (runOnStart) this.emit(name); 23 | 24 | const interval = setInterval(() => { 25 | this.emit(name); 26 | }, sampling); 27 | 28 | this.timers.push(interval); 29 | } 30 | } else { 31 | this.timers.forEach(clearInterval); 32 | this.timers = []; 33 | } 34 | 35 | this.timersState = state; 36 | this.emit('state', state); 37 | return true; 38 | } 39 | } 40 | 41 | export default ImpulseGenerator; 42 | 43 | 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": false, 3 | "displayName": "Enphase Envoy", 4 | "name": "homebridge-enphase-envoy", 5 | "version": "10.3.8", 6 | "description": "Homebridge p7ugin for Photovoltaic Energy System manufactured by Enphase.", 7 | "license": "MIT", 8 | "author": "grzegorz914", 9 | "maintainers": [ 10 | "grzegorz914" 11 | ], 12 | "homepage": "https://github.com/grzegorz914/homebridge-enphase-envoy#readme", 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/grzegorz914/homebridge-enphase-envoy.git" 16 | }, 17 | "bugs": { 18 | "url": "https://github.com/grzegorz914/homebridge-enphase-envoy/issues" 19 | }, 20 | "type": "module", 21 | "exports": { 22 | ".": "./index.js" 23 | }, 24 | "files": [ 25 | "src", 26 | "index.js", 27 | "config.schema.json", 28 | "package.json", 29 | "CHANGELOG.md", 30 | "README.md", 31 | "LICENSE" 32 | ], 33 | "engines": { 34 | "homebridge": "^1.8.0 || ^2.0.0 || ^2.0.0-beta.40 || ^2.0.0-alpha.60", 35 | "node": "^20 || ^22 || ^24 || ^25" 36 | }, 37 | "dependencies": { 38 | "mqtt": "^5.14.1", 39 | "axios": "^1.13.2", 40 | "express": "^5.2.1", 41 | "fast-xml-parser": "^5.3.3", 42 | "fakegato-history": "^0.6.7" 43 | }, 44 | "keywords": [ 45 | "homebridge", 46 | "homebridge-plugin", 47 | "envoy", 48 | "enphase", 49 | "ensemble", 50 | "enpower", 51 | "encharge", 52 | "photovoltaic", 53 | "solar", 54 | "mqtt", 55 | "restful" 56 | ], 57 | "contributors": [], 58 | "scripts": { 59 | "test": "echo \"Error: no test specified\" && exit 1" 60 | } 61 | } -------------------------------------------------------------------------------- /src/digestauth.js: -------------------------------------------------------------------------------- 1 | import crypto from 'crypto'; 2 | import axios from 'axios'; 3 | 4 | class DigestAuth { 5 | constructor(config) { 6 | this.user = config.user; 7 | this.passwd = config.passwd; 8 | this.count = 0; 9 | } 10 | 11 | async request(path, options) { 12 | const url = `${options.baseURL}${path}`; 13 | options.headers = options.headers || {}; 14 | 15 | try { 16 | return await axios.request(url, options); 17 | } catch (error) { 18 | const resError = error.response; 19 | if (!resError || resError.status !== 401) throw new Error(`Digest authentication response error: ${resError ? resError.status : 'Unknown error'}`); 20 | 21 | const resHeaders = resError.headers["www-authenticate"]; 22 | if (!resHeaders || !resHeaders.includes('nonce')) throw new Error(`Digest authentication headers error: ${resHeaders || 'Header not found'}`); 23 | 24 | try { 25 | const authDetails = {}; 26 | resHeaders.match(/(\w+)=("([^"]+)"|([^,]+))/g).forEach(part => { 27 | const match = part.match(/(\w+)=("([^"]+)"|([^,]+))/); 28 | authDetails[match[1]] = match[3] || match[4]; 29 | }); 30 | 31 | const realm = authDetails.realm; 32 | const nonce = authDetails.nonce; 33 | const nonceCount = (`00000000${this.count++}`).slice(-8); 34 | const cnonce = crypto.randomBytes(24).toString('hex'); 35 | 36 | const md5 = str => crypto.createHash('md5').update(str).digest('hex'); 37 | const HA1 = md5(`${this.user}:${realm}:${this.passwd}`); 38 | const HA2 = md5(`${options.method}:${path}`); 39 | const response = md5(`${HA1}:${nonce}:${nonceCount}:${cnonce}:auth:${HA2}`); 40 | const authHeader = `Digest username="${this.user}", realm="${realm}", nonce="${nonce}", uri="${path}", qop=auth, algorithm=MD5, response="${response}", nc=${nonceCount}, cnonce="${cnonce}"`; 41 | options.headers["authorization"] = authHeader; 42 | 43 | return await axios.request(url, options); 44 | } catch (error) { 45 | throw new Error(`Digest authentication error: ${error}`); 46 | } 47 | } 48 | } 49 | } 50 | 51 | export default DigestAuth; 52 | 53 | -------------------------------------------------------------------------------- /src/passwdcalc.js: -------------------------------------------------------------------------------- 1 | import crypto from 'crypto'; 2 | 3 | class PasswdCalc { 4 | constructor(config) { 5 | this.user = config.user; 6 | this.realm = config.realm; 7 | this.serialNumber = config.serialNumber; 8 | } 9 | 10 | async getPasswd() { 11 | try { 12 | const hashString = `[e]${this.user}@${this.realm}#${this.serialNumber} EnPhAsE eNeRgY `; 13 | const inputString = crypto.createHash('md5').update(hashString).digest('hex'); 14 | const digestIterator = this.digestSnippet(inputString); 15 | 16 | const counters = inputString.split("").reduce((acc, val) => { 17 | if (val === "0") acc[0]++; 18 | else if (val === "1") acc[1]++; 19 | return acc; 20 | }, [0, 0]); 21 | 22 | let [countZero, countOne] = counters; 23 | let password = ''; 24 | 25 | const MAX_ZERO = 20; 26 | const MAX_ONE = 26; 27 | const SKIP_ZERO = [3, 6, 9]; 28 | const SKIP_ONE = [9, 15]; 29 | 30 | for (const cc of digestIterator) { 31 | if (SKIP_ZERO.includes(countZero)) countZero--; 32 | if (countZero > MAX_ZERO) countZero = MAX_ZERO; 33 | if (countZero < 0) countZero = 0; 34 | 35 | if (SKIP_ONE.includes(countOne)) countOne--; 36 | if (countOne > MAX_ONE) countOne = MAX_ONE; 37 | if (countOne < 0) countOne = 0; 38 | 39 | switch (cc) { 40 | case "0": 41 | password += String.fromCharCode('f'.charCodeAt(0) + countZero); 42 | countZero--; 43 | break; 44 | case "1": 45 | password += String.fromCharCode('@'.charCodeAt(0) + countOne); 46 | countOne--; 47 | break; 48 | default: 49 | password += cc; 50 | break; 51 | } 52 | } 53 | 54 | return password; 55 | } catch (error) { 56 | throw new Error(`Generate password error: ${error}`); 57 | } 58 | } 59 | 60 | *digestSnippet(inputString) { 61 | for (let i = inputString.length - 1; i > inputString.length - 9; i--) { 62 | yield inputString[i]; 63 | } 64 | } 65 | } 66 | 67 | export default PasswdCalc; -------------------------------------------------------------------------------- /src/envoytoken.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { URLSearchParams } from 'url'; 3 | import EventEmitter from 'events'; 4 | import { EnphaseUrls } from './constants.js'; 5 | 6 | class EnvoyToken extends EventEmitter { 7 | constructor(config) { 8 | super(); 9 | this.user = config.user; 10 | this.passwd = config.passwd; 11 | this.serialNumber = config.serialNumber; 12 | this.logWarn = config.logWarn; 13 | this.logError = config.logError; 14 | } 15 | 16 | async refreshToken() { 17 | try { 18 | const cookie = await this.loginToEnlighten(); 19 | if (!cookie) return null; 20 | 21 | const tokenData = await this.getToken(cookie); 22 | if (!tokenData) return null; 23 | 24 | // Determine if token is installer or user (12h = 43200 seconds) 25 | const installerToken = (tokenData.expires_at - tokenData.generation_time) === 43200; 26 | tokenData.installer = installerToken; 27 | 28 | this.emit('success', `Token ${installerToken ? 'installer' : 'user'}, expires at: ${new Date(tokenData.expires_at * 1000).toLocaleString()}`); 29 | 30 | return tokenData; 31 | } catch (error) { 32 | throw new Error(`Refresh token error: ${error}`); 33 | } 34 | } 35 | 36 | async loginToEnlighten() { 37 | try { 38 | const form = new URLSearchParams(); 39 | form.append('user[email]', this.user); 40 | form.append('user[password]', this.passwd); 41 | 42 | const response = await axios({ 43 | method: 'POST', 44 | baseURL: EnphaseUrls.BaseUrl, 45 | url: EnphaseUrls.Login, 46 | headers: { 47 | 'Content-Type': 'application/x-www-form-urlencoded' 48 | }, 49 | data: form, 50 | timeout: 10000 51 | }); 52 | 53 | if (response.status !== 200) { 54 | if (this.logError) this.emit('error', `Login failed with status code: ${response.status}`); 55 | return null; 56 | } 57 | 58 | const cookie = response.headers['set-cookie']; 59 | if (!cookie) { 60 | if (this.logWarn) this.emit('warn', `No cookie returned from login. Response headers: ${JSON.stringify(response.headers)}`); 61 | return null; 62 | } 63 | 64 | return cookie; 65 | } catch (error) { 66 | throw new Error(`Login to Enlighten error: ${error}`); 67 | } 68 | } 69 | 70 | async getToken(cookie) { 71 | try { 72 | const response = await axios({ 73 | method: 'GET', 74 | baseURL: EnphaseUrls.BaseUrl, 75 | url: EnphaseUrls.EntrezAuthToken, 76 | params: { 77 | serial_num: this.serialNumber 78 | }, 79 | headers: { 80 | Accept: 'application/json', 81 | Cookie: cookie 82 | }, 83 | timeout: 10000 84 | }); 85 | 86 | const tokenData = response.data; 87 | 88 | if (!tokenData.token || !tokenData.expires_at || !tokenData.generation_time) { 89 | if (this.logWarn) this.emit('warn', `Incomplete token data: ${JSON.stringify(tokenData)}`); 90 | return null; 91 | } 92 | 93 | return tokenData; 94 | } catch (error) { 95 | throw new Error(`Get token error: ${error}`); 96 | } 97 | } 98 | } 99 | 100 | export default EnvoyToken; 101 | 102 | 103 | -------------------------------------------------------------------------------- /src/mqtt.js: -------------------------------------------------------------------------------- 1 | import { connect } from 'mqtt'; 2 | import EventEmitter from 'events'; 3 | 4 | class Mqtt extends EventEmitter { 5 | constructor(config) { 6 | super(); 7 | 8 | const url = `mqtt://${config.host}:${config.port}`; 9 | const subscribeTopic = `${config.prefix}/Set`; 10 | 11 | const options = { 12 | clientId: config.clientId, 13 | username: config.user, 14 | password: config.passwd, 15 | protocolVersion: 5, 16 | clean: false, 17 | properties: { 18 | sessionExpiryInterval: 60 * 60, // 1 hour 19 | userProperties: { 20 | source: 'node-client' 21 | } 22 | } 23 | }; 24 | 25 | this.mqttClient = connect(url, options); 26 | 27 | // === CONNECTED === 28 | this.mqttClient.on('connect', async (packet) => { 29 | this.emit('connected', 'MQTT v5 connected.'); 30 | 31 | try { 32 | const result = await this.mqttClient.subscribeAsync(subscribeTopic, { 33 | qos: 1, 34 | properties: { 35 | userProperties: { 36 | type: 'subscription' 37 | } 38 | } 39 | }); 40 | 41 | // MQTT v5 subscription results contain reason codes 42 | if (config.logDebug) this.emit('debug', `Subscribed to ${subscribeTopic}, reason codes: ${JSON.stringify(result)}`); 43 | this.emit('subscribed', `MQTT Subscribe topic: ${subscribeTopic}`); 44 | 45 | } catch (error) { 46 | if (config.logWarn) this.emit('warn', `MQTT Subscribe error: ${error}`); 47 | } 48 | }); 49 | 50 | // === MESSAGE === 51 | this.mqttClient.on('message', (topic, payload, packet) => { 52 | try { 53 | const obj = JSON.parse(payload.toString()); 54 | if (config.logDebug) this.emit('debug', `MQTT Received:\nTopic: ${topic}\nPayload: ${JSON.stringify(obj, null, 2)}\nProperties: ${JSON.stringify(packet.properties, null, 2)}`); 55 | 56 | const key = Object.keys(obj)[0]; 57 | const value = Object.values(obj)[0]; 58 | this.emit('set', key, value); 59 | 60 | } catch (error) { 61 | if (config.logWarn) this.emit('warn', `MQTT Parse error: ${error}`); 62 | } 63 | }); 64 | 65 | // === PUBLISH EVENT === 66 | this.on('publish', async (topic, message) => { 67 | try { 68 | const fullTopic = `${config.prefix}/${topic}`; 69 | const publishMessage = JSON.stringify(message); 70 | 71 | await this.mqttClient.publishAsync(fullTopic, publishMessage, { 72 | qos: 1, 73 | properties: { 74 | contentType: 'application/json', 75 | userProperties: { 76 | source: 'node', 77 | action: 'set' 78 | } 79 | } 80 | }); 81 | 82 | if (config.logDebug) this.emit('debug', `MQTT Publish:\nTopic: ${fullTopic}\nPayload: ${publishMessage}`); 83 | } catch (error) { 84 | if (config.logWarn) this.emit('warn', `MQTT Publish error: ${error}`); 85 | } 86 | }); 87 | 88 | // === ERRORS / STATE === 89 | this.mqttClient.on('error', (err) => { 90 | this.emit('warn', `MQTT Error: ${err.message}`); 91 | }); 92 | 93 | this.mqttClient.on('reconnect', () => { 94 | if (config.logDebug) this.emit('debug', 'MQTT Reconnecting...'); 95 | }); 96 | 97 | this.mqttClient.on('close', () => { 98 | if (config.logDebug) this.emit('debug', 'MQTT Connection closed.'); 99 | }); 100 | } 101 | } 102 | 103 | export default Mqtt; -------------------------------------------------------------------------------- /src/restful.js: -------------------------------------------------------------------------------- 1 | import express, { json } from 'express'; 2 | import EventEmitter from 'events'; 3 | 4 | const DEFAULT_MESSAGE = 'This data is not available in your system.'; 5 | 6 | class RestFul extends EventEmitter { 7 | constructor(config) { 8 | super(); 9 | this.port = config.port; 10 | this.logWarn = config.logWarn; 11 | this.logDebug = config.logDebug; 12 | 13 | this.restFulData = { 14 | token: DEFAULT_MESSAGE, 15 | info: DEFAULT_MESSAGE, 16 | home: DEFAULT_MESSAGE, 17 | inventory: DEFAULT_MESSAGE, 18 | microinvertersstatus: DEFAULT_MESSAGE, 19 | meters: DEFAULT_MESSAGE, 20 | metersreading: DEFAULT_MESSAGE, 21 | metersreports: DEFAULT_MESSAGE, 22 | detaileddevicesdata: DEFAULT_MESSAGE, 23 | microinvertersdata: DEFAULT_MESSAGE, 24 | qrelaysdata: DEFAULT_MESSAGE, 25 | homedata: DEFAULT_MESSAGE, 26 | metersdata: DEFAULT_MESSAGE, 27 | production: DEFAULT_MESSAGE, 28 | productionpdm: DEFAULT_MESSAGE, 29 | energypdm: DEFAULT_MESSAGE, 30 | productionct: DEFAULT_MESSAGE, 31 | powerandenergydata: DEFAULT_MESSAGE, 32 | acbatterydata: DEFAULT_MESSAGE, 33 | ensembleinventory: DEFAULT_MESSAGE, 34 | ensemblestatus: DEFAULT_MESSAGE, 35 | ensemblepower: DEFAULT_MESSAGE, 36 | enchargesettings: DEFAULT_MESSAGE, 37 | tariff: DEFAULT_MESSAGE, 38 | drycontacts: DEFAULT_MESSAGE, 39 | drycontactssettings: DEFAULT_MESSAGE, 40 | generator: DEFAULT_MESSAGE, 41 | generatorsettings: DEFAULT_MESSAGE, 42 | ensembledata: DEFAULT_MESSAGE, 43 | gridprofile: DEFAULT_MESSAGE, 44 | livedata: DEFAULT_MESSAGE, 45 | livedatadata: DEFAULT_MESSAGE, 46 | productionstate: DEFAULT_MESSAGE, 47 | plclevel: DEFAULT_MESSAGE, 48 | datasampling: DEFAULT_MESSAGE 49 | }; 50 | 51 | this.connect(); 52 | } 53 | 54 | connect() { 55 | try { 56 | const app = express(); 57 | app.set('json spaces', 2); 58 | app.use(json()); 59 | 60 | // Create GET routes directly from field names 61 | for (const key of Object.keys(this.restFulData)) { 62 | app.get(`/${key}`, (req, res) => { 63 | res.json(this.restFulData[key]); 64 | }); 65 | } 66 | 67 | // Health check route 68 | app.get('/status', (req, res) => { 69 | res.json({ 70 | status: 'online', 71 | uptime: process.uptime(), 72 | available_paths: Object.keys(this.restFulData).map(k => `/${k}`) 73 | }); 74 | }); 75 | 76 | // POST route 77 | app.post('/', (req, res) => { 78 | try { 79 | const obj = req.body; 80 | if (!obj || typeof obj !== 'object' || Object.keys(obj).length === 0) { 81 | if (this.logWarn) this.emit('warn', 'RESTFul Invalid JSON payload'); 82 | return res.status(400).json({ error: 'RESTFul Invalid JSON payload' }); 83 | } 84 | 85 | const key = Object.keys(obj)[0]; 86 | const value = obj[key]; 87 | this.emit('set', key, value); 88 | this.update(key, value); 89 | 90 | if (this.logDebug) this.emit('debug', `RESTFul post data: ${JSON.stringify(obj, null, 2)}`); 91 | 92 | res.json({ success: true, received: obj }); 93 | } catch (error) { 94 | if (this.logWarn) this.emit('warn', `RESTFul Parse error: ${error}`); 95 | res.status(500).json({ error: 'RESTFul Internal Server Error' }); 96 | } 97 | }); 98 | 99 | app.listen(this.port, () => { 100 | this.emit('connected', `RESTful started on port: ${this.port}`); 101 | }); 102 | } catch (error) { 103 | if (this.logWarn) this.emit('warn', `RESTful Connect error: ${error}`); 104 | } 105 | } 106 | 107 | update(path, data) { 108 | if (this.restFulData.hasOwnProperty(path)) { 109 | this.restFulData[path] = data; 110 | if (this.logDebug) this.emit('debug', `RESTFul update path: ${path}, data: ${JSON.stringify(data, null, 2)}`); 111 | } else { 112 | if (this.logWarn) this.emit('warn', `RESTFul update failed. Unknown path: "${path}". Valid paths: ${Object.keys(this.restFulData).join(', ')}`); 113 | } 114 | } 115 | } 116 | 117 | export default RestFul; 118 | 119 | -------------------------------------------------------------------------------- /src/functions.js: -------------------------------------------------------------------------------- 1 | import { promises as fsPromises } from 'fs'; 2 | import axios from 'axios'; 3 | import { Agent } from 'https'; 4 | import { ApiCodes, TimezoneLocaleMap } from './constants.js'; 5 | 6 | class Functions { 7 | constructor() { 8 | } 9 | 10 | async saveData(path, data, stringify = true) { 11 | try { 12 | data = stringify ? JSON.stringify(data, null, 2) : data; 13 | await fsPromises.writeFile(path, data); 14 | return true; 15 | } catch (error) { 16 | throw new Error(`Save data error: ${error}`); 17 | } 18 | } 19 | 20 | async readData(path, parseJson = false) { 21 | try { 22 | const data = await fsPromises.readFile(path, 'utf8'); 23 | 24 | if (parseJson) { 25 | if (!data.trim()) { 26 | // Empty file when expecting JSON 27 | return null; 28 | } 29 | try { 30 | return JSON.parse(data); 31 | } catch (jsonError) { 32 | throw new Error(`JSON parse error in file "${path}": ${jsonError.message}`); 33 | } 34 | } 35 | 36 | // For non-JSON, just return file content (can be empty string) 37 | return data; 38 | } catch (error) { 39 | if (error.code === 'ENOENT') { 40 | // File does not exist 41 | return null; 42 | } 43 | // Preserve original error details 44 | const wrappedError = new Error(`Read data error for "${path}": ${error.message}`); 45 | wrappedError.original = error; 46 | throw wrappedError; 47 | } 48 | } 49 | 50 | async getStatus(status) { 51 | if (!Array.isArray(status) || status.length === 0) { 52 | return 'OK'; 53 | } 54 | 55 | const mapped = status.map(a => { 56 | const value = ApiCodes[a]; 57 | return (typeof value === 'string' && value.trim() !== '') ? value.trim() : a; 58 | }).filter(Boolean); // Remove any empty/null/undefined values 59 | 60 | if (mapped.length === 0) { 61 | return 'OK'; 62 | } 63 | 64 | const result = mapped.join(', '); 65 | 66 | // Add ellipsis only if result is actually truncated 67 | return result.length > 64 ? result.slice(0, 61) + '…' : result; 68 | } 69 | 70 | isValidValue(v) { 71 | return v !== undefined && v !== null && !(typeof v === 'number' && Number.isNaN(v)); 72 | } 73 | 74 | scaleValue(value, inMin, inMax, outMin, outMax) { 75 | if (!this.isValidValue(value) || !this.isValidValue(inMin) || !this.isValidValue(inMax) || !this.isValidValue(outMin) || !this.isValidValue(outMax)) return null; 76 | 77 | if (inMax === inMin) return outMin; 78 | if (value <= inMin) return outMin; 79 | if (value >= inMax) return outMax; 80 | 81 | const scaled = ((value - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin; 82 | if (scaled > outMax) return outMax; 83 | 84 | return scaled < 0.5 ? outMin : Math.round(scaled); 85 | } 86 | 87 | evaluateCompareMode(value, threshold, mode) { 88 | switch (mode) { 89 | case 0: return value > threshold; 90 | case 1: return value >= threshold; 91 | case 2: return value === threshold; 92 | case 3: return value < threshold; 93 | case 4: return value <= threshold; 94 | case 5: return value !== threshold; 95 | default: return false; 96 | } 97 | } 98 | 99 | formatTimestamp(ts, timezone) { 100 | const locale = TimezoneLocaleMap[timezone] || 'en-US'; 101 | const options = { 102 | timeZone: timezone, 103 | year: 'numeric', 104 | month: '2-digit', 105 | day: '2-digit', 106 | hour: '2-digit', 107 | minute: '2-digit', 108 | second: '2-digit', 109 | }; 110 | 111 | if (!ts) { 112 | return new Date().toLocaleString(locale, options); 113 | } 114 | 115 | const numeric = Number(ts); 116 | if (Number.isInteger(numeric)) { 117 | const ms = numeric < 1e12 ? numeric * 1000 : numeric; 118 | return new Date(ms).toLocaleString(locale, options); 119 | } 120 | 121 | return ts; 122 | } 123 | 124 | powerPeak(power, powerPeakStored) { 125 | if (!this.isValidValue(power) && !this.isValidValue(powerPeakStored)) return null; 126 | if (!this.isValidValue(power)) return powerPeakStored; 127 | if (!this.isValidValue(powerPeakStored)) return power; 128 | 129 | // dodatnie — szczyt rośnie w górę 130 | if (power >= 0 && power > powerPeakStored) return power; 131 | 132 | // ujemne — szczyt rośnie w dół 133 | if (power < 0 && power < powerPeakStored) return power; 134 | 135 | return powerPeakStored; 136 | } 137 | 138 | createAxiosInstance(url, authHeader = null, cookie = null) { 139 | return axios.create({ 140 | baseURL: url, 141 | headers: { 142 | Accept: 'application/json', 143 | ...(authHeader ? { Authorization: authHeader } : {}), 144 | ...(cookie ? { Cookie: cookie } : {}), 145 | }, 146 | withCredentials: true, 147 | httpsAgent: new Agent({ 148 | keepAlive: false, 149 | rejectUnauthorized: false 150 | }), 151 | timeout: 60000 152 | }); 153 | } 154 | 155 | } 156 | export default Functions -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | import { mkdirSync, existsSync, writeFileSync } from 'fs'; 3 | import EnvoyDevice from './src/envoydevice.js'; 4 | import ImpulseGenerator from './src/impulsegenerator.js'; 5 | import { PluginName, PlatformName } from './src/constants.js'; 6 | import CustomCharacteristics from './src/customcharacteristics.js'; 7 | 8 | class EnvoyPlatform { 9 | constructor(log, config, api) { 10 | if (!config || !Array.isArray(config.devices)) { 11 | log.warn(`No configuration found for ${PluginName}.`); 12 | return; 13 | } 14 | 15 | this.log = log; 16 | this.accessories = []; 17 | 18 | const prefDir = join(api.user.storagePath(), 'enphaseEnvoy'); 19 | try { 20 | mkdirSync(prefDir, { recursive: true }); 21 | } catch (error) { 22 | log.error(`Prepare directory error: ${error}.`); 23 | return; 24 | } 25 | 26 | api.on('didFinishLaunching', async () => { 27 | for (let i = 0; i < config.devices.length; i++) { 28 | const device = config.devices[i]; 29 | const displayType = device.displayType || 0; 30 | if (displayType === 0) continue; 31 | 32 | const deviceName = device.name; 33 | const host = device.host || (i === 0 ? 'envoy.local' : `envoy-${i + 1}.local`); 34 | const { envoyFirmware7xxTokenGenerationMode = 0, envoyToken, enlightenUser, enlightenPasswd } = device; 35 | 36 | const logLevel = { 37 | devInfo: device.log?.deviceInfo || true, 38 | success: device.log?.success || true, 39 | info: device.log?.info || false, 40 | warn: device.log?.warn || true, 41 | error: device.log?.error || true, 42 | debug: device.log?.debug || false 43 | }; 44 | 45 | if (!deviceName) { 46 | log.warn(`Device: ${host}, Name missing.`); 47 | continue; 48 | } 49 | 50 | if (envoyFirmware7xxTokenGenerationMode === 1 && (!enlightenUser || !enlightenPasswd)) { 51 | log.warn(`Device: ${host} ${deviceName}, missing Enlighten credentials.`); 52 | continue; 53 | } 54 | 55 | if (envoyFirmware7xxTokenGenerationMode === 2 && !envoyToken) { 56 | log.warn(`Device: ${host} ${deviceName}, missing Envoy token.`); 57 | continue; 58 | } 59 | 60 | if (logLevel.debug) { 61 | log.info(`Device: ${host} ${deviceName}, did finish launching.`); 62 | const redactedConfig = JSON.stringify({ 63 | ...device, 64 | envoyPasswd: 'removed', 65 | envoyToken: 'removed', 66 | enlightenPasswd: 'removed', 67 | mqtt: { 68 | auth: { 69 | ...device.mqtt?.auth, 70 | passwd: 'removed', 71 | } 72 | }, 73 | }, null, 2); 74 | log.info(`Device: ${host} ${deviceName}, Config: ${redactedConfig}`); 75 | } 76 | 77 | const postFix = host.split('.').join(''); 78 | const envoyIdFile = join(prefDir, `envoyId_${postFix}`); 79 | const envoyTokenFile = join(prefDir, `envoyToken_${postFix}`); 80 | const energyMeterHistoryFileName = `energyMeterHistory_${postFix}`; 81 | 82 | try { 83 | [envoyIdFile, envoyTokenFile].forEach(file => { 84 | if (!existsSync(file)) writeFileSync(file, '0'); 85 | }); 86 | } catch (error) { 87 | if (logLevel.error) log.error(`Device: ${host} ${deviceName}, File init error: ${error}`); 88 | continue; 89 | } 90 | 91 | try { 92 | const url = envoyFirmware7xxTokenGenerationMode > 0 ? `https://${host}` : `http://${host}`; 93 | 94 | // create impulse generator 95 | const impulseGenerator = new ImpulseGenerator() 96 | .on('start', async () => { 97 | try { 98 | const envoyDevice = new EnvoyDevice(api, log, url, deviceName, device, envoyIdFile, envoyTokenFile, prefDir, energyMeterHistoryFileName) 99 | .on('devInfo', (info) => log.info(info)) 100 | .on('success', (msg) => log.success(`Device: ${host} ${deviceName}, ${msg}`)) 101 | .on('info', (msg) => log.info(`Device: ${host} ${deviceName}, ${msg}`)) 102 | .on('debug', (msg, data) => log.info(`Device: ${host} ${deviceName}, debug: ${data ? `${msg} ${JSON.stringify(data, null, 2)}` : msg}`)) 103 | .on('warn', (msg) => log.warn(`Device: ${host} ${deviceName}, ${msg}`)) 104 | .on('error', (msg) => log.error(`Device: ${host} ${deviceName}, ${msg}`)); 105 | 106 | const accessories = await envoyDevice.start(); 107 | if (accessories) { 108 | api.publishExternalAccessories(PluginName, accessories); 109 | if (logLevel.success) log.success(`Device: ${host} ${deviceName}, Published as external accessory.`); 110 | 111 | await impulseGenerator.state(false); 112 | await envoyDevice.startStopImpulseGenerator(true); 113 | } 114 | } catch (error) { 115 | if (logLevel.error) log.error(`Device: ${host} ${deviceName}, Start impulse generator error: ${error}, retrying.`); 116 | } 117 | }) 118 | .on('state', state => { 119 | if (logLevel.debug) log.info(`Device: ${host} ${deviceName}, Start impulse generator ${state ? 'started' : 'stopped'}.`); 120 | }); 121 | 122 | // start impulse generator 123 | await impulseGenerator.state(true, [{ name: 'start', sampling: 120000 }]); 124 | } catch (error) { 125 | if (logLevel.error) log.error(`Device: ${host} ${deviceName}, Did finish launching error: ${error}`); 126 | } 127 | } 128 | }); 129 | } 130 | 131 | configureAccessory(accessory) { 132 | this.accessories.push(accessory); 133 | } 134 | } 135 | 136 | export default (api) => { 137 | CustomCharacteristics(api); 138 | api.registerPlatform(PluginName, PlatformName, EnvoyPlatform); 139 | }; 140 | 141 | -------------------------------------------------------------------------------- /enphase_envoy.15s.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | # By grzegorz914@icloud.com 4 | # see https://github.com/grzegorz914/homebridge-enphase-envoy 5 | 6 | # Enphase Envoy 7 | # v1.0 8 | # Grzegorz 9 | # grzegorz914 10 | # Display the power and energy of Enphase solar system. 11 | # ruby 12 | # http://url-to-about.com/ 13 | 14 | require 'net/http' 15 | require 'net/http/digest_auth' 16 | require 'json' 17 | 18 | ENVOY_IP = 'envoy.local' 19 | MICROINVERTERS_SUM_WATTS = 5400 # Set the summary power of microinverters 20 | 21 | def autoFormatPower(val) 22 | if (val < 1000 && val > -1000) 23 | return val.round(1).to_s + ' W' 24 | end 25 | if ((val >= 1000 && val < 1000000) || (val > -1000000 && val <= -1000)) 26 | return (val/1000).round(3).to_s + ' kW' 27 | end 28 | if (val <= -1000000 || val >= 1000000) 29 | return (val/1000000).round(3).to_s + ' MW' 30 | end 31 | end 32 | 33 | def autoFormatEnergy(val) 34 | if (val < 1000 && val > -1000) 35 | return val.round(1).to_s + ' Wh' 36 | end 37 | if ((val >= 1000 && val < 1000000) || (val > -1000000 && val <= -1000)) 38 | return (val/1000).round(3).to_s + ' kWh' 39 | end 40 | if (val <= -1000000 || val >= 1000000) 41 | return (val/1000000).round(3).to_s + ' MWh' 42 | end 43 | end 44 | 45 | begin 46 | raise "Not a valid IP address. Update ENVOY_IP in script" unless ENVOY_IP.match(/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/) 47 | http = Net::HTTP.new(ENVOY_IP) 48 | 49 | # Check installed meters 50 | uri = URI("http://" + ENVOY_IP + "/ivp/meters") 51 | req = Net::HTTP::Get.new(uri.request_uri) 52 | res = http.request(req) 53 | raise "Error on meters response: " + res.message unless res.is_a?(Net::HTTPSuccess) 54 | meters = JSON.parse(res.body) 55 | 56 | # Check enabled meters 57 | ctmeters = meters.length 58 | if ctmeters > 0 59 | ctmeterProduction = (meters[0]["state"] == "enabled") 60 | ctmeterConsumption = (meters[1]["state"] == "enabled") 61 | else 62 | ctmeterProduction = false 63 | ctmeterConsumption = false 64 | end 65 | 66 | # Get production misroinverters 67 | uri = URI("http://" + ENVOY_IP + "/api/v1/production") 68 | req = Net::HTTP::Get.new(uri.request_uri) 69 | res = http.request(req) 70 | raise "Error on production response: " + res.message unless res.is_a?(Net::HTTPSuccess) 71 | production = JSON.parse(res.body) 72 | 73 | productionMicroSummarywhToday = production["attHoursToday"] 74 | productionMicroSummarywhLastSevenDays = production["wattHoursSevenDays"] 75 | productionMicroSummarywhLifeTime = production["wattHoursLifetime"] 76 | productionMicroSummaryWattsNow = production["wattsNow"] 77 | 78 | # Get production cureent meters 79 | uri = URI("http://" + ENVOY_IP + "/production.json?details=1") 80 | req = Net::HTTP::Get.new(uri.request_uri) 81 | res = http.request(req) 82 | raise "Error on productionct response: " + res.message unless res.is_a?(Net::HTTPSuccess) 83 | productionct = JSON.parse(res.body) 84 | 85 | if ctmeterProduction == true 86 | productionPower = productionct["production"][1]["wNow"] 87 | productionEnergyToday = productionct["production"][1]["whToday"] 88 | productionEnergyLastSevenDays = productionct["production"][1]["whLastSevenDays"] 89 | productionEnergyLifeTime = productionct["production"][1]["whLifetime"] 90 | end 91 | 92 | if ctmeterConsumption == true 93 | consumptionTotalPower = productionct["consumption"][0]["wNow"] 94 | consumptionTotalEnergyToday = productionct["consumption"][0]["whToday"] 95 | consumptionTotalEnergyLastSevenDays = productionct["consumption"][0]["whLastSevenDays"] 96 | consumptionTotalEnergyLifeTime = productionct["consumption"][0]["whLifetime"] 97 | consumptionNetPower = productionct["consumption"][1]["wNow"] 98 | consumptionNetEnergyLifeTime = productionct["consumption"][1]["whLifetime"] 99 | end 100 | 101 | if ctmeterConsumption == true 102 | case 103 | when consumptionNetPower > 0 104 | icon = "🔌" # Power plug 105 | power = consumptionNetPower 106 | when (ctmeterProduction ? productionPower : productionMicroSummaryWattsNow) < (MICROINVERTERS_SUM_WATTS / 2) 107 | icon = "⛅" # Cloudy 108 | power = ctmeterProduction ? productionPower : productionMicroSummaryWattsNow 109 | else 110 | icon = "☀️" # Sun 111 | power = ctmeterProduction ? productionPower : productionMicroSummaryWattsNow 112 | end 113 | else 114 | case 115 | when (ctmeterProduction ? productionPower : productionMicroSummaryWattsNow) < (MICROINVERTERS_SUM_WATTS / 2) 116 | icon = "⛅" # Cloudy 117 | power = ctmeterProduction ? productionPower : productionMicroSummaryWattsNow 118 | else 119 | icon = "☀️" # Sun 120 | power = ctmeterProduction ? productionPower : productionMicroSummaryWattsNow 121 | end 122 | end 123 | 124 | puts "#{icon} #{autoFormatPower(power)}| color=#{power > 0 ? "red":"white"} size=12" 125 | puts "---" 126 | puts "Production" 127 | puts "Power #{autoFormatPower(ctmeterProduction ? productionPower : productionMicroSummaryWattsNow)}| size=12" 128 | puts "Energy #{autoFormatEnergy(ctmeterProduction ? productionEnergyToday : productionMicroSummarywhToday)}| size=12" 129 | puts "Energy 7 days #{autoFormatEnergy(ctmeterProduction ? productionEnergyLastSevenDays : productionMicroSummarywhLastSevenDays)}| size=12" 130 | puts "Energy lifetime #{autoFormatEnergy(ctmeterProduction ? productionEnergyLifeTime : productionMicroSummarywhLifeTime)}| size=12" 131 | puts "---" 132 | if ctmeterConsumption == true 133 | puts "Consumption total" 134 | puts "Power #{autoFormatPower(consumptionTotalPower)}| size=12" 135 | puts "Energy #{autoFormatEnergy(consumptionTotalEnergyToday)}| size=12" 136 | puts "Energy 7 days #{autoFormatEnergy(consumptionTotalEnergyLastSevenDays)}| size=12" 137 | puts "Energy lifetime #{autoFormatEnergy(consumptionTotalEnergyLifeTime)}| size=12" 138 | puts "---" 139 | puts "Consumption net" 140 | puts "Power #{autoFormatPower(consumptionNetPower)}| size=12" 141 | puts "Energy lifetime #{autoFormatEnergy(consumptionNetEnergyLifeTime)}| size=12" 142 | puts "---" 143 | end 144 | 145 | # Get installed and active devices 146 | uri = URI("http://" + ENVOY_IP + "/inventory.json") 147 | req = Net::HTTP::Get.new(uri.request_uri) 148 | res = http.request(req) 149 | raise "Error on inventory response: " + res.message unless res.is_a?(Net::HTTPSuccess) 150 | inventory = JSON.parse(res.body) 151 | 152 | # Get the serial number of the envoy 153 | uri = URI("http://" + ENVOY_IP + "/info.xml") 154 | req = Net::HTTP::Get.new(uri.request_uri) 155 | res = http.request(req) 156 | raise "Error on envoy serial response: " + res.message unless res.is_a?(Net::HTTPSuccess) 157 | envoySerial = res.body.scan(/sn>(\d*)<\/sn>/).first.first 158 | 159 | # Now lets see how much the every microinverter producing. 160 | uri = URI("http://" + ENVOY_IP + "/api/v1/production/inverters") 161 | uri.user = "envoy" 162 | uri.password = envoySerial[-6,6] 163 | 164 | # Make the first request to get the auth 165 | req = Net::HTTP::Get.new(uri.request_uri) 166 | res = http.request(req) 167 | 168 | # Aauthentication digest 169 | digest_auth = Net::HTTP::DigestAuth.new 170 | auth = digest_auth.auth_header(uri, res['www-authenticate'], 'GET') 171 | req = Net::HTTP::Get.new(uri.request_uri) 172 | req.add_field('Authorization', auth) 173 | res = http.request(req) 174 | 175 | # Get serial number and power of every microinverter 176 | case res 177 | when Net::HTTPSuccess 178 | allInverters = JSON.parse(res.body) 179 | puts "Mikroinwerter" 180 | j = 0 181 | arr = Array.new 182 | arr1 = Array.new 183 | loop do 184 | serialNumber = allInverters[j]["serialNumber"] 185 | power = allInverters[j]["lastReportWatts"] 186 | arr.push(serialNumber) 187 | arr1.push(power) 188 | j += 1 189 | if j == allInverters.length 190 | break 191 | end 192 | end 193 | 194 | i = 0 195 | loop do 196 | serial = inventory[0]["devices"][i]["serial_num"] 197 | index = arr.find_index(serial) 198 | puts "Nr. #{arr[index]} moc: #{autoFormatPower(arr1[index])}| size=12" 199 | i += 1 200 | if i == inventory[0]["devices"].length 201 | break 202 | puts "---" 203 | end 204 | end 205 | when Net::HTTPUnauthorized 206 | {'error' => "#{res.message}: username and password set and correct?"} 207 | when Net::HTTPServerError 208 | {'error' => "#{res.message}: try again later?"} 209 | else 210 | {'error' => res.message} 211 | end 212 | 213 | rescue StandardError => e 214 | puts ":warning: Error| size=12" 215 | puts "---" 216 | puts e.message 217 | end 218 | -------------------------------------------------------------------------------- /sample-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "bridge": { 3 | "name": "Homebridge", 4 | "username": "AA:BB:CC:DD:EE:FF", 5 | "manufacturer": "homebridge.io", 6 | "model": "homebridge", 7 | "port": 9100, 8 | "pin": "123-45-678" 9 | }, 10 | "description": "HomeKit Bridge", 11 | "ports": { 12 | "start": 9101, 13 | "end": 9150, 14 | "comment": "In this section set the port for Homebridge accessories." 15 | }, 16 | "accessories": [], 17 | "platforms": [ 18 | { 19 | "platform": "enphaseEnvoy", 20 | "devices": [ 21 | { 22 | "name": "Envoy", 23 | "host": "192.168.1.35", 24 | "displayType": 1, 25 | "envoyFirmware7xxTokenGenerationMode": 0, 26 | "envoyPasswd": "", 27 | "enlightenUser": "", 28 | "enlightenPasswd": "", 29 | "envoyToken": "", 30 | "envoyTokenInstaller": false, 31 | "lockControl": { 32 | "enable": true, 33 | "time": 30, 34 | "namePrefix": false 35 | }, 36 | "productionStateSensor": { 37 | "name": "Sensor name", 38 | "displayType": 0, 39 | "namePrefix": false 40 | }, 41 | "plcLevelControl": { 42 | "name": "Control name", 43 | "displayType": 0, 44 | "namePrefix": false 45 | }, 46 | "powerProductionSummary": 7200, 47 | "powerProductionLevelSensors": [ 48 | { 49 | "name": "Production > 7500W", 50 | "compareMode": 0, 51 | "powerLevel": 7500, 52 | "displayType": 0, 53 | "namePrefix": false 54 | } 55 | ], 56 | "energyProductionLifetimeOffset": 0, 57 | "energyProductionLevelSensors": [ 58 | { 59 | "name": "Production energy level > 5000Wh", 60 | "compareMode": 0, 61 | "energyLevel": 5000, 62 | "displayType": 0, 63 | "namePrefix": false 64 | } 65 | ], 66 | "gridProductionQualitySensors": [ 67 | { 68 | "displayType": 0, 69 | "name": "Cyrrent > 5A", 70 | "compareMode": 0, 71 | "compareType": 0, 72 | "compareevel": 5, 73 | "namePrefix": false 74 | } 75 | ], 76 | "powerConsumptionTotalLevelSensors": [ 77 | { 78 | "name": "Consumption Total > 5500W", 79 | "compareMode": 0, 80 | "powerLevel": 5500, 81 | "displayType": 0, 82 | "namePrefix": false 83 | } 84 | ], 85 | "energyConsumptionTotalLifetimeOffset": 0, 86 | "energyConsumptionTotalLevelSensors": [ 87 | { 88 | "name": "Consumption Total energy level > 5000Wh", 89 | "compareMode": 0, 90 | "energyLevel": 5000, 91 | "displayType": 0, 92 | "namePrefix": false 93 | } 94 | ], 95 | "gridConsumptionTotalQualitySensors": [ 96 | { 97 | "displayType": 0, 98 | "name": "Cyrrent > 5A", 99 | "compareMode": 0, 100 | "compareType": 0, 101 | "compareevel": 5, 102 | "namePrefix": false 103 | } 104 | ], 105 | "powerConsumptionNetLevelSensors": [ 106 | { 107 | "name": "Import from Net > 5500W", 108 | "compareMode": 0, 109 | "powerLevel": 5500, 110 | "displayType": 0, 111 | "namePrefix": false 112 | }, 113 | { 114 | "name": "Export to Net = 5500W", 115 | "compareMode": 2, 116 | "powerLevel": -5500, 117 | "displayType": 0, 118 | "namePrefix": false 119 | } 120 | ], 121 | "energyConsumptionNetLifetimeOffset": 0, 122 | "energyConsumptionNetLevelSensors": [ 123 | { 124 | "name": "Consumption Net energy level >= 5000Wh", 125 | "compareMode": 0, 126 | "energyLevel": 5000, 127 | "displayType": 0, 128 | "namePrefix": false 129 | } 130 | ], 131 | "gridConsumptionNetQualitySensors": [ 132 | { 133 | "displayType": 0, 134 | "name": "Cyrrent > 5A", 135 | "compareMode": 0, 136 | "compareType": 0, 137 | "compareevel": 5, 138 | "namePrefix": false 139 | } 140 | ], 141 | "qRelayStateSensor": { 142 | "name": "Sensor name", 143 | "displayType": 0, 144 | "namePrefix": false, 145 | "multiphase": false 146 | }, 147 | "acBatterieName": "AC batterie name", 148 | "acBatterieBackupLevelSummaryAccessory": { 149 | "displayType": 0, 150 | "minSoc": 0 151 | }, 152 | "acBatterieBackupLevelAccessory": { 153 | "displayType": 0, 154 | "minSoc": 0 155 | }, 156 | "enpowerGridStateControl": { 157 | "name": "Control name", 158 | "displayType": 0, 159 | "namePrefix": false 160 | }, 161 | "enpowerGridStateSensor": { 162 | "name": "Sensor name", 163 | "displayType": 0, 164 | "namePrefix": false 165 | }, 166 | "enpowerGridModeSensors": [ 167 | { 168 | "name": "Sensor name", 169 | "mode": "On", 170 | "displayType": 0, 171 | "namePrefix": false 172 | } 173 | ], 174 | "enchargeName": "Encharge name", 175 | "enchargeBackupLevelSummaryAccessory": { 176 | "displayType": 0, 177 | "minSoc": 0 178 | }, 179 | "enchargeBackupLevelAccessory": { 180 | "displayType": 0, 181 | "minSoc": 0 182 | }, 183 | "enchargeStateSensor": { 184 | "name": "Sensor name", 185 | "displayType": 0, 186 | "namePrefix": false 187 | }, 188 | "enchargeProfileControls": [ 189 | { 190 | "name": "Tile name", 191 | "profile": "self-consumption", 192 | "displayType": 0, 193 | "namePrefix": false 194 | } 195 | ], 196 | "enchargeProfileSensors": [ 197 | { 198 | "name": "Sensor name", 199 | "profile": "self-consumption", 200 | "displayType": 0, 201 | "namePrefix": false 202 | } 203 | ], 204 | "enchargeGridStateSensor": { 205 | "name": "Sensor name", 206 | "displayType": 0, 207 | "namePrefix": false 208 | }, 209 | "enchargeGridModeSensors": [ 210 | { 211 | "name": "Sensor name", 212 | "gridMode": "grid-on", 213 | "displayType": 0, 214 | "namePrefix": false 215 | } 216 | ], 217 | "enchargeBackupLevelSensors": [ 218 | { 219 | "name": "Backup > 50%", 220 | "compareMode": 0, 221 | "backupLevel": 100, 222 | "displayType": 0, 223 | "namePrefix": false 224 | } 225 | ], 226 | "solarGridStateSensor": { 227 | "name": "Sensor name", 228 | "displayType": 0, 229 | "namePrefix": false 230 | }, 231 | "solarGridModeSensors": [ 232 | { 233 | "name": "Sensor name", 234 | "gridMode": "grid-on", 235 | "displayType": 0, 236 | "namePrefix": false 237 | } 238 | ], 239 | "enpowerDryContactsControl": false, 240 | "enpowerDryContactsSensor": false, 241 | "generatorStateControl": { 242 | "name": "Control name", 243 | "displayType": 0, 244 | "namePrefix": false 245 | }, 246 | "generatorStateSensor": { 247 | "name": "Sensor name", 248 | "displayType": 0, 249 | "namePrefix": false 250 | }, 251 | "generatordModeContol": [ 252 | { 253 | "name": "Tile name", 254 | "mode": "auto", 255 | "displayType": 0, 256 | "namePrefix": false 257 | } 258 | ], 259 | "generatordModeSensors": [ 260 | { 261 | "name": "Sensor name", 262 | "mode": "off", 263 | "displayType": 0, 264 | "namePrefix": false 265 | } 266 | ], 267 | "dataRefreshControl": { 268 | "name": "Control name", 269 | "displayType": 0, 270 | "namePrefix": false 271 | }, 272 | "dataRefreshSensor": { 273 | "name": "Sensor name", 274 | "displayType": 0, 275 | "namePrefix": false 276 | }, 277 | "metersDataRefreshTime": 3.0, 278 | "productionDataRefreshTime": 5.0, 279 | "liveDataRefreshTime": 3.0, 280 | "ensembleDataRefreshTime": 15.0, 281 | "log": { 282 | "deviceInfo": true, 283 | "success": true, 284 | "info": false, 285 | "warn": true, 286 | "error": true, 287 | "debug": false 288 | }, 289 | "restFul": { 290 | "enable": false, 291 | "port": 3000 292 | }, 293 | "mqtt": { 294 | "enable": false, 295 | "host": "", 296 | "port": 1883, 297 | "clientId": "", 298 | "prefix": "", 299 | "auth": { 300 | "enable": false, 301 | "user": "", 302 | "passwd": "" 303 | } 304 | } 305 | } 306 | ] 307 | } 308 | ] 309 | } -------------------------------------------------------------------------------- /src/constants.js: -------------------------------------------------------------------------------- 1 | export const PlatformName = "enphaseEnvoy"; 2 | export const PluginName = "homebridge-enphase-envoy"; 3 | export const DisplayName = "Enphase Envoy"; 4 | export const Authorization = { 5 | "EnvoyUser": "envoy", 6 | "InstallerUser": "installer", 7 | "Realm": "enphaseenergy.com" 8 | }; 9 | 10 | export const EnphaseUrls = { 11 | "BaseUrl": "https://enlighten.enphaseenergy.com", 12 | "Login": "/login/login.json", 13 | "EntrezAuthToken": "/entrez-auth-token" 14 | }; 15 | 16 | export const EntrezUrls = { 17 | "BaseUrl": "https://entrez.enphaseenergy.com", 18 | "Login": "/login", 19 | "Tokens": "/tokens" 20 | }; 21 | 22 | export const ApiUrls = { 23 | "AcbSleepModeGetSetCancel": "/admin/lib/acb_config.json", 24 | "AddLoadKontrolKit": "/ivp/ss/load_control", 25 | "AgfProfileIndex": "/installer/agf/index.json?simplified=true", 26 | "AgfProfileDetails": "/installer/agf/details.json", 27 | "AgfProfileInverterStatus": "/installer/agf/inverters_status.json", 28 | "AgfProfileSetProfile": "/installer/agf/set_profile.json", 29 | "BackboneApplication": "/backbone/application.js", 30 | "CellularConfig": "/admin/lib/network_display.json?cellular=1", 31 | "CheckJwt": "/auth/check_jwt", 32 | "ClearGFIPost": "/admin/lib/admin_dcc_display.json", 33 | "DerSettings": "/ivp/ss/der_settings", 34 | "DevStatus": "/ivp/peb/devstatus", 35 | "DevicesData": "/ivp/pdm/device_data", 36 | "DryContacts": "/ivp/ensemble/dry_contacts", 37 | "DryContactsSettings": "/ivp/ss/dry_contact_settings", 38 | "EnchargeBattery": "/ivp/ensemble/power", 39 | "EnchargeChargingDischargingStatus": "/ivp/sc/sched", 40 | "EnchargeRelay": "/ivp/ensemble/relay", 41 | "EnchargeGetSetCancelSleepMode": "/ivp/ensemble/sleep", 42 | "EnchargeSettings": "/ivp/ss/enc_settings", 43 | "EnchrgeStatus": "/ivp/sc/status", 44 | "EnsembleAgfProfileStatus": "/ivp/ensemble/profile_status", 45 | "EnsembleComm": "/ivp/ensemble/comm_check", 46 | "EnsembleDeletePut": "/ivp/zb/provision", 47 | "EnsembleInventory": "/ivp/ensemble/inventory", 48 | "EnsembleSecctrl": "/ivp/ensemble/secctrl", 49 | "EnsembleStatus": "/ivp/ensemble/status", 50 | "EnsemblePower": "/ivp/ensemble/power", 51 | "EthernetConfigCheckNewIpGetPut": "/admin/lib/network_display.json", 52 | "EventsGet": "/datatab/event_dt.rb", 53 | "Generator": "/ivp/ensemble/generator", 54 | "GeneratorDelete": "/ivp/ss/gen_delete", 55 | "GeneratorMeterStateSet": "/ivp/ss/generator_meter_enable", 56 | "GeneratorModeGetSet": "/ivp/ss/gen_mode", 57 | "GeneratorProfileGetSet": "/ivp/ss/gen_profile", 58 | "GeneratorScheduleGetSet": "/ivp/ss/gen_schedule", 59 | "GeneratorSettingsGetSet": "/ivp/ss/gen_config", 60 | "GetInfo": "/info.xml", 61 | "GetTimezones": "/admin/lib/date_time_display.json?tzlist=1", 62 | "Home": "/home.json", 63 | "InternalMeterCurrentCtSettings": "/ivp/meters/cts", 64 | "InternalMeterCurrentCtSettingsEid": "/ivp/meters/cts/EID", 65 | "InternalMeterInfo": "/ivp/meters", 66 | "InternalMeterInfoEid": "/ivp/meters/EID", 67 | "InternalMeterInfoStorage": "/ivp/meters/storage_settings", 68 | "InternalMeterRevelsalEid": "/ivp/meters/ctreversal/EID", 69 | "InternalMeterReadings": "/ivp/meters/readings", 70 | "InternalMeterReadingsEid": "/ivp/meters/readings/EID", 71 | "InternalMeterStream": "/stream/meter", 72 | "InternalMetersReports": "/ivp/meters/reports/", 73 | "InternalMetersReportsProduction": "/ivp/meters/reports/production", 74 | "InternalMetersReportsConsumption": "/ivp/meters/reports/consumption", 75 | "InverterComm": "/installer/pcu_comm_check", 76 | "InverterDelete": "/prov", 77 | "InverterProduction": "/api/v1/production/inverters", 78 | "InverterPut": "/prov", 79 | "Inventory": "/inventory.json", 80 | "InventoryDeleted": "/inventory.json?deleted=1", 81 | "LiveDataStatus": "/ivp/livedata/status", 82 | "LiveDataStream": "/ivp/livedata/stream", 83 | "NewScanGetPD": "/ivp/peb/newscan", 84 | "ProductionPdm": "/ivp/pdm/production", 85 | "EnergyPdm": "/ivp/pdm/energy", 86 | "Production": "/api/v1/production", 87 | "Energy": "/api/v1/energy", 88 | "PMUGetPost": "/admin/lib/admin_pmu_display.json", 89 | "PowerControlSystemGetSet": "/ivp/ss/pcs_settings", 90 | "PowerExportLimitGet": "/ivp/ss/pel_settings", 91 | "PowerForcedModeGetPut": "/ivp/mod/EID/mode/power", 92 | "Profile": "/ivp/arf/profile", 93 | "Pvlimit": "/ivp/sc/pvlimit", 94 | "RedeterminePhase": "/ivp/grest/local/gs/redeterminephase", 95 | "ReportSettingsGetPut": "/ivp/peb/reportsettings", 96 | "SendPhaseInformation": "/ivp/ss/sys_phase_balance", 97 | "SetTimezone": "/admin/lib/date_time_display.json", 98 | "SystemReadingStats": "/production.json?details=1", 99 | "TariffSettingsGetPut": "/admin/lib/tariff", 100 | "TunnelStateGetPut": "/admin/lib/dba.json", 101 | "UpdateMeterConfig": "/ivp/meters/EID", 102 | "UpdateMeterCurrentCTConfig": "/ivp/meters/cts/EID", 103 | "UpdatePassword": "/admin/lib/security_display.json", 104 | "WifiSettingsGetJoin": "/admin/lib/wireless_display.json" 105 | }; 106 | 107 | export const PartNumbers = { 108 | "800-00551-r03": "X-IQ-AM1-120-B-M", 109 | "800-00553-r03": "X-IQ-AM1-240-B", 110 | "800-00557-r03": "X-IQ-AM1-240-BM", 111 | "800-00554-r04": "X-IQ-AM1-240-2", 112 | "800-00554-r05": "X-IQ-AM1-240-2-M", 113 | "800-00555-r03": "X-IQ-AM1-240-3", 114 | "800-00655-r09": "X-IQ-AM1-240-3-ES", 115 | "800-00556-r03": "X-IQ-AM1-240-3C", 116 | "800-00554-r07": "X-IQ-AM1-240-3C-ES", 117 | "880-00122-r02": "ENV-S-AB-120-A", 118 | "880-00210-r02": "ENV-S-AM1-120", 119 | "800-00552-r01": "ENV-S-WM-230", 120 | "800-00553-r01": "ENV-S-WB-230", 121 | "800-00553-r02": "ENV-S-WB-230-F", 122 | "800-00554-r03": "ENV-S-WM-230", 123 | "800-00654-r06": "ENV-S-WM-230", 124 | "800-00654-r08": "ENV-S-WM-230", 125 | "800-00664-r05": "ENV-S-WM-230", 126 | "880-00208-r02": "ENV-IQ-AM1-240", 127 | "880-00208-r03": "ENV-IQ-AM1-240", 128 | "880-00231-r02": "ENV-IQ-AM1-240", 129 | "880-00209-r03": "ENV-IQ-AM3-3P", 130 | "880-00557-r02": "ENV-IQ-AM3-3P", 131 | "860-00152-r02": "Q-RELAY-1P-INT", 132 | "800-00598-r04": "Q-RELAY-1P-INT", 133 | "800-00597-r02": "Q-RELAY-3P-INT", 134 | "800-00630-r02": "IQ7-60-2-INT", 135 | "800-00637-r02": "IQ7-60-2-US", 136 | "800-00641-r02": "IQ7-60-B-US", 137 | "800-00633-r02": "IQ7A-72-2-INT", 138 | "800-00634-r02": "IQ7A-72-2-US", 139 | "800-00638-r02": "IQ7A-72-B-US", 140 | "800-00632-r02": "IQ7X-96-2-INT", 141 | "800-00635-r02": "IQ7X-96-2-US", 142 | "800-00639-r02": "IQ7X-96-B-US", 143 | "800-00631-r02": "IQ7PLUS-72-2-INT", 144 | "880-01736-r02": "IQ7PLUS-72-M-INT", 145 | "800-00636-r02": "IQ7PLUS-72-2-US", 146 | "800-00640-r02": "IQ7PLUS-72-B-US", 147 | "883-00852-r09": "IQ7PLUS-72-2-US", 148 | "800-01131-r02": "IQ8", 149 | "800-01395-r03": "IQ8AC-72-M-INT", 150 | "860-00276-r48": "EP200G101-M240US00", 151 | "830-00703-r75": "B03-A01-US00-1-3", 152 | "830-00703-r84": "B03-A01-US00-1-3", 153 | "836-01890-r24": "ENCHARGE-IQ-5P", 154 | "836-00750-r27": "ENCHARGE-10-1P-NA", 155 | "860-00376-r38": "ENPOWER", 156 | "860-00276-r59": "ENPOWER", 157 | "800-01612-r04": "ENSEMBLE", 158 | "865-00400-r22": "IQ Meter Collar", 159 | "800-02403-r08": "IQ Combiner C6", 160 | "836-01250-r00": "IQ Battery 10C", 161 | "xxx-xxxxx-xx3": "COMMS-KIT-01", 162 | "834-01927-r03": "COMMS-KIT-02" 163 | }; 164 | 165 | export const ApiCodes = { 166 | "ACB": "AC Batterie", 167 | "BLE": "BLE", 168 | "CAN": "CAN", 169 | "COLLAR": "Collar", 170 | "C6 COMBINER CONTROLER": "C6 Combiner Controller", 171 | "C6 RGM": "C6 Revenue Grade Meter", 172 | "ENCHARGE": "Encharge", 173 | "ENCHG_STATE_CHARGING": "Encharge state charging", 174 | "ENCHG_STATE_DISCHARGING": "Encharge state discharging", 175 | "ENCHG_STATE_IDLE": "Encharge state idle", 176 | "ENCHG_STATE_READY": "Encharge state ready", 177 | "ENCMN_MDE_ENCHARGE_READY": "Encharge mode ready", 178 | "ENCMN_MDE_ON_GRID": "Encharge mode on grid", 179 | "ENCMN_MDE_OFF_GRID": "Encharge mode off grid", 180 | "ENCMN_C6_CC_READY": "C6 Combiner Controller ready", 181 | "ENPOWER": "Enpower", 182 | "ENS_DEVICE_STATE_READY": "Ensemble state ready", 183 | "ENPWR_STATE_GRIDMODE_CONFIRM": "Enpower state grid mode confirm", 184 | "ENPWR_STATE_GRIDMODE_WAIT": "Enpower state grid mode wait", 185 | "ENPWR_STATE_OPER_CLOSED": "Enpower state closed", 186 | "ENPWR_STATE_OPER_NO_GRID": "Enpower state no grid", 187 | "ENPWR_STATE_OPER_OPEN": "Enpower state open", 188 | "ENPWR_STATE_OPER_SYNC_READY": "Enpower state sync ready", 189 | "ESUB": "Ensemble", 190 | "NSRB": "Q-Relay", 191 | "PCU": "Microinverter", 192 | "StorageTouMode_DEFAULT_TOU_MODE": "Default tou mode", 193 | "USB": "USB", 194 | "Unknown": "Unknown", 195 | "always_on": "Always On", 196 | "apply": "Apply", 197 | "auto": "Auto", 198 | "backup": "Full backup", 199 | "backfeed": "Back Feed", 200 | "cellular": "Cellular", 201 | "charging": "Charging", 202 | "check-wiring": "Check Wiring", 203 | "close": "Close", 204 | "closed": "Closed", 205 | "connected": "Connected", 206 | "consumption": "Consumption Net", 207 | "discharging": "Discharging", 208 | "disabled": "Disabled", 209 | "disconnected": "Disconnected", 210 | "economy": "Economy", 211 | "eim": "Current Meter", 212 | "enabled": "Enabled", 213 | "encharge": "Encharge", 214 | "enpower": "Enpower", 215 | "esub": "Ensemble", 216 | "eth0": "Ethernet", 217 | "ethernet": "Ethernet", 218 | "evse": "EV Charger", 219 | "flat": "Flat", 220 | "full": "Full", 221 | "gen": "Generstor", 222 | "grid-forming": "Grid Forming", 223 | "grid-interactive": "Grid Interactive", 224 | "grid-tied": "Grid Tied", 225 | "idle": "Idle", 226 | "inverters": "Microinverters", 227 | "load": "Load", 228 | "manual": "Manual", 229 | "multimode-offgrid": "Multimode Grid OFF", 230 | "multimode-ongrid": "Multimode Grid ON", 231 | "net-consumption": "Consumption Net", 232 | "negative-production": "Negative production", 233 | "negative-total-consumption": "Negative total consumption", 234 | "none": "None", 235 | "normal": "Normal", 236 | "not-metering": "Not metering", 237 | "not-satisfied": "Not satisfied", 238 | "not_set": "Not set", 239 | "nsrb": "Q-Relay", 240 | "off": "Off", 241 | "off-grid": "Grid OFF", 242 | "off_grid": "Grid OFF", 243 | "on": "On", 244 | "on-grid": "Grid ON", 245 | "on_grid": "Grid ON", 246 | "one": "One", 247 | "open": "Open", 248 | "open synchronized": "Open Synchronized", 249 | "open synchronizing": "Open Synchronizing", 250 | "pcu": "Microinverter", 251 | "ph-a": "L1", 252 | "ph-b": "L2", 253 | "ph-c": "L3", 254 | "ph-all": "All", 255 | "ph-unk": "Unknown", 256 | "pmu": "Power Meter Unit", 257 | "power-on-unused-phase": "Powwr on unused phase", 258 | "production": "Production", 259 | "production-imbalance": "Production imbalance", 260 | "prop.done": "Prop done", 261 | "prop.not.done": "Prop not done", 262 | "pv": "PV", 263 | "pv3p": "PV 3 Phase", 264 | "ready": "Ready", 265 | "rgm": "Revenue Grade Meter", 266 | "satisfied": "Satisfied", 267 | "savings-mode": "Savings", 268 | "self-consumption": "Self consumption", 269 | "shed": "Shed", 270 | "shedule": "Shedule", 271 | "single": "Single", 272 | "single_rate": "Single rate", 273 | "soc": "State oF Charge", 274 | "split": "Split", 275 | "storage": "Storage", 276 | "subghz": "Sub GHz", 277 | "synchronizing-to-grid": "Synchronizing to grid", 278 | "three": "Three", 279 | "tiered": "Tiered", 280 | "time_of_use": "Time of use", 281 | "time_to_use": "Time to use", 282 | "total-consumption": "Consumption Total", 283 | "two": "Two", 284 | "unknown": "Unknown", 285 | "utility-interactive": "Utility Interactive", 286 | "wifi": "WiFi", 287 | "wlan0": "WiFi", 288 | "zigbee": "ZigBee", 289 | "envoy.cond_flags.acb_ctrl.bmudatabounds": "BMU Data Bounds Error", 290 | "envoy.cond_flags.acb_ctrl.bmuhardwareerror": "BMU Hardware Error", 291 | "envoy.cond_flags.acb_ctrl.bmuimageerror": "BMU Image Error", 292 | "envoy.cond_flags.acb_ctrl.bmumaxcurrentwarning": "BMU Max Current Warning", 293 | "envoy.cond_flags.acb_ctrl.bmusenseerror": "BMU Sense Error", 294 | "envoy.cond_flags.acb_ctrl.cellmaxtemperror": "Cell Max Temperature Error", 295 | "envoy.cond_flags.acb_ctrl.cellmaxtempwarning": "Cell Max Temperature Warning", 296 | "envoy.cond_flags.acb_ctrl.cellmaxvoltageerror": "Cell Max Voltage Error", 297 | "envoy.cond_flags.acb_ctrl.cellmaxvoltagewarning": "Cell Max Voltage Warning", 298 | "envoy.cond_flags.acb_ctrl.cellmintemperror": "Cell Min Temperature Error", 299 | "envoy.cond_flags.acb_ctrl.cellmintempwarning": "Cell Min Temperature Warning", 300 | "envoy.cond_flags.acb_ctrl.cellminvoltageerror": "Cell Min Voltage Error", 301 | "envoy.cond_flags.acb_ctrl.cellminvoltagewarning": "Cell Min Voltage Warning", 302 | "envoy.cond_flags.acb_ctrl.cibcanerror": "CIB CAN Error", 303 | "envoy.cond_flags.acb_ctrl.cibimageerror": "CIB Image Error", 304 | "envoy.cond_flags.acb_ctrl.cibspierror": "CIB SPI Error", 305 | "envoy.cond_flags.nsrb_ctrl.acfreqhigh": "AC Frequency High", 306 | "envoy.cond_flags.nsrb_ctrl.acfreqlow": "AC Frequency Low", 307 | "envoy.cond_flags.nsrb_ctrl.acfrequencyoor": "AC Frequency Out Of Range", 308 | "envoy.cond_flags.nsrb_ctrl.acvoltageavgline1": "AC Voltage Avg Out Of Range - Phase 1", 309 | "envoy.cond_flags.nsrb_ctrl.acvoltageavgline2": "AC Voltage Avg Out Of Range - Phase 2", 310 | "envoy.cond_flags.nsrb_ctrl.acvoltageavgline3": "AC Voltage Avg Out Of Range - Phase 3", 311 | "envoy.cond_flags.nsrb_ctrl.acvoltagehighline1": "AC Voltage High - Phase 1", 312 | "envoy.cond_flags.nsrb_ctrl.acvoltagehighline2": "AC Voltage Out Of Range - Phase 2", 313 | "envoy.cond_flags.nsrb_ctrl.acvoltagehighline3": "AC Voltage High - Phase 3", 314 | "envoy.cond_flags.nsrb_ctrl.acvoltagelowline1": "AC Voltage Low - Phase 1", 315 | "envoy.cond_flags.nsrb_ctrl.acvoltagelowline2": "AC Voltage Out Of Range - Phase 2", 316 | "envoy.cond_flags.nsrb_ctrl.acvoltagelowline3": "AC Voltage Low - Phase 3", 317 | "envoy.cond_flags.nsrb_ctrl.acvoltageoorline1": "AC Voltage Out Of Range - Phase 1", 318 | "envoy.cond_flags.nsrb_ctrl.acvoltageoorline2": "AC Voltage Out Of Range - Phase 2", 319 | "envoy.cond_flags.nsrb_ctrl.acvoltageoorline3": "AC Voltage Out Of Range - Phase 3", 320 | "envoy.cond_flags.nsrb_ctrl.buttonpress": "Button Pressed", 321 | "envoy.cond_flags.nsrb_ctrl.dcgriderror": "DC Grid Current Error", 322 | "envoy.cond_flags.nsrb_ctrl.dcgridhigh": "DC Grid Current High", 323 | "envoy.cond_flags.nsrb_ctrl.dcgridlow": "DC Grid Current Low", 324 | "envoy.cond_flags.nsrb_ctrl.relayforced": "Relay Forced", 325 | "envoy.cond_flags.nsrb_ctrl.relayopen": "Relay Open", 326 | "envoy.cond_flags.nsrb_ctrl.rocof": "Rate of Change of Frequency Error", 327 | "envoy.cond_flags.obs_strs.discovering": "Discovering", 328 | "envoy.cond_flags.obs_strs.failure": "Failure to report", 329 | "envoy.cond_flags.obs_strs.flasherror": "Flash Error", 330 | "envoy.cond_flags.obs_strs.notmonitored": "Not Monitored", 331 | "envoy.cond_flags.obs_strs.ok": "Normal", 332 | "envoy.cond_flags.obs_strs.plmerror": "PLM Error", 333 | "envoy.cond_flags.obs_strs.secmodeenterfailure": "Secure mode enter failure", 334 | "envoy.cond_flags.obs_strs.secmodeexitfailure": "Secure mode exit failure", 335 | "envoy.cond_flags.obs_strs.sleeping": "Sleep Mode On", 336 | "envoy.cond_flags.obs_strs.verifing": "Verifying Device", 337 | "envoy.cond_flags.pcu_chan.acMonitorError": "AC Monitor Error", 338 | "envoy.cond_flags.pcu_chan.acfrequencyhigh": "AC Frequency High", 339 | "envoy.cond_flags.pcu_chan.acfrequencylow": "AC Frequency Low", 340 | "envoy.cond_flags.pcu_chan.acfrequencyoor": "AC Frequency Out Of Range", 341 | "envoy.cond_flags.pcu_chan.acvoltage_avg_hi": "AC Voltage Average High", 342 | "envoy.cond_flags.pcu_chan.acvoltagehigh": "AC Voltage High", 343 | "envoy.cond_flags.pcu_chan.acvoltagelow": "AC Voltage Low", 344 | "envoy.cond_flags.pcu_chan.acvoltageoor": "AC Voltage Out Of Range", 345 | "envoy.cond_flags.pcu_chan.acvoltageoosp1": "AC Voltage Out Of Range - Phase 1", 346 | "envoy.cond_flags.pcu_chan.acvoltageoosp2": "AC Voltage Out Of Range - Phase 2", 347 | "envoy.cond_flags.pcu_chan.acvoltageoosp3": "AC Voltage Out Of Range - Phase 3", 348 | "envoy.cond_flags.pcu_chan.agfpowerlimiting": "AGF Power Limiting", 349 | "envoy.cond_flags.pcu_chan.dcresistancelow": "DC Resistance Low", 350 | "envoy.cond_flags.pcu_chan.dcresistancelowpoweroff": "DC Resistance Low - Power Off", 351 | "envoy.cond_flags.pcu_chan.dcvoltagetoohigh": "DC Voltage Too High", 352 | "envoy.cond_flags.pcu_chan.dcvoltagetoolow": "DC Voltage Too Low", 353 | "envoy.cond_flags.pcu_chan.dfdt": "AC Frequency Changing too Fast", 354 | "envoy.cond_flags.pcu_chan.gfitripped": "GFI Tripped", 355 | "envoy.cond_flags.pcu_chan.gridgone": "Grid Gone", 356 | "envoy.cond_flags.pcu_chan.gridinstability": "Grid Instability", 357 | "envoy.cond_flags.pcu_chan.gridoffsethi": "Grid Offset Hi", 358 | "envoy.cond_flags.pcu_chan.gridoffsetlow": "Grid Offset Low", 359 | "envoy.cond_flags.pcu_chan.hardwareError": "Hardware Error", 360 | "envoy.cond_flags.pcu_chan.hardwareWarning": "Hardware Warning", 361 | "envoy.cond_flags.pcu_chan.highskiprate": "High Skip Rate", 362 | "envoy.cond_flags.pcu_chan.invalidinterval": "Invalid Interval", 363 | "envoy.cond_flags.pcu_chan.pwrgenoffbycmd": "Power generation off by command", 364 | "envoy.cond_flags.pcu_chan.skippedcycles": "Skipped Cycles", 365 | "envoy.cond_flags.pcu_chan.vreferror": "Voltage Ref Error", 366 | "envoy.cond_flags.pcu_ctrl.altpwrgenmode": "Alternate Power Generation Mode", 367 | "envoy.cond_flags.pcu_ctrl.altvfsettings": "Alternate Voltage and Frequency Settings", 368 | "envoy.cond_flags.pcu_ctrl.badflashimage": "Bad Flash Image", 369 | "envoy.cond_flags.pcu_ctrl.bricked": "No Grid Profile", 370 | "envoy.cond_flags.pcu_ctrl.commandedreset": "Commanded Reset", 371 | "envoy.cond_flags.pcu_ctrl.criticaltemperature": "Critical Temperature", 372 | "envoy.cond_flags.pcu_ctrl.dc-pwr-low": "DC Power Too Low", 373 | "envoy.cond_flags.pcu_ctrl.iuplinkproblem": "IUP Link Problem", 374 | "envoy.cond_flags.pcu_ctrl.lertactive": "Alert Active", 375 | "envoy.cond_flags.pcu_ctrl.manutestmode": "In Manu Test Mode", 376 | "envoy.cond_flags.pcu_ctrl.nsync": "Grid Perturbation Unsynchronized", 377 | "envoy.cond_flags.pcu_ctrl.overtemperature": "Over Temperature", 378 | "envoy.cond_flags.pcu_ctrl.poweronreset": "Power On Reset", 379 | "envoy.cond_flags.pcu_ctrl.pwrgenoffbycmd": "Power generation off by command", 380 | "envoy.cond_flags.pcu_ctrl.runningonac": "Running on AC", 381 | "envoy.cond_flags.pcu_ctrl.sleep-mode": "Sleep Mode On", 382 | "envoy.cond_flags.pcu_ctrl.tpmtest": "Transient Grid Profile", 383 | "envoy.cond_flags.pcu_ctrl.unexpectedreset": "Unexpected Reset", 384 | "envoy.cond_flags.pcu_ctrl.watchdogreset": "Watchdog Reset", 385 | "envoy.cond_flags.rgm_chan.check_meter": "Meter Error", 386 | "envoy.cond_flags.rgm_chan.power_quality": "Poor Power Quality", 387 | "envoy.cond_flags.undef-0x00020000": "Status 0x00020000", 388 | "envoy.global.ok": "Normal" 389 | }; 390 | 391 | export const MetersKeyMap = { 392 | "production": "production", 393 | "net-consumption": "consumptionNet", 394 | "total-consumption": "consumptionTotal", 395 | "storage": "storage", 396 | "gen": "gen", 397 | "backfeed": "backfeed", 398 | "evse": "evse", 399 | "load": "load", 400 | "pv3p": "pv3p" 401 | }; 402 | 403 | export const MetersKeyMap1 = { 404 | "Production": "production", 405 | "Consumption Net": "consumptionNet", 406 | "Consumption Total": "consumptionTotal", 407 | "Storage": "storage", 408 | "Generator": "generator", 409 | }; 410 | 411 | export const DeviceTypeMap = { 412 | 1: "Microinverter", 413 | 12: "Q-Relay", 414 | 13: "Encharge", 415 | 14: "Encharge Sub Module", 416 | 15: "Encharge Control Module", 417 | 17: "Enpower", 418 | 18: "Enpower Sub Module", 419 | 20: "Enpower Control Module", 420 | 19: "Ensemble", 421 | 22: "Ensemble Comm Module", 422 | 24: "Ensemble Comm Control Module", 423 | }; 424 | 425 | export const LedStatus = { 426 | "0": "Off", 427 | "1": "Standby", 428 | "2": "Booting", 429 | "3": "Initializing", 430 | "4": "Connected", 431 | "5": "Firmware Update", 432 | "7": "Warning", 433 | "8": "Error", 434 | "9": "Critical Error", 435 | "10": "Maintenance", 436 | "11": "Testing", 437 | "12": "Charging", 438 | "13": "Discharging", 439 | "14": "Idle", 440 | "15": "Reserved", 441 | "16": "Reserved", 442 | "17": "Reserved", 443 | "18": "Unknown", 444 | "19": "Unknown", 445 | "20": "Unknown" 446 | }; 447 | 448 | export const TimezoneLocaleMap = { 449 | // US / North America 450 | "America/Los_Angeles": "en-US", // Pacific Time 451 | "US/Pacific": "en-US", 452 | "America/Denver": "en-US", // Mountain Time 453 | "US/Mountain": "en-US", 454 | "America/Chicago": "en-US", // Central Time 455 | "US/Central": "en-US", 456 | "America/New_York": "en-US", // Eastern Time 457 | "US/Eastern": "en-US", 458 | "America/Anchorage": "en-US", 459 | "Pacific/Honolulu": "en-US", 460 | 461 | "America/Vancouver": "en-CA", 462 | "Canada/Pacific": "en-CA", 463 | "America/Toronto": "en-CA", 464 | "Canada/Eastern": "en-CA", 465 | "America/Halifax": "en-CA", 466 | "Canada/Atlantic": "en-CA", 467 | 468 | "Mexico/BajaNorte": "en-US", 469 | "Mexico/BajaSur": "en-US", 470 | 471 | // Europe 472 | "Europe/London": "en-GB", 473 | "Europe/Dublin": "en-IE", 474 | "Europe/Paris": "fr-FR", 475 | "Europe/Berlin": "de-DE", 476 | "Europe/Madrid": "es-ES", 477 | "Europe/Rome": "it-IT", 478 | "Europe/Warsaw": "pl-PL", 479 | "Europe/Amsterdam": "nl-NL", 480 | "Europe/Brussels": "fr-BE", 481 | "Europe/Zurich": "de-CH", 482 | "Europe/Vienna": "de-AT", 483 | "Europe/Stockholm": "sv-SE", 484 | "Europe/Helsinki": "fi-FI", 485 | "Europe/Athens": "el-GR", 486 | "Europe/Moscow": "ru-RU", 487 | 488 | // Asia 489 | "Asia/Tokyo": "ja-JP", 490 | "Asia/Shanghai": "zh-CN", 491 | "Asia/Hong_Kong": "zh-HK", 492 | "Asia/Singapore": "en-SG", 493 | "Asia/Kolkata": "hi-IN", 494 | "Asia/Seoul": "ko-KR", 495 | "Asia/Bangkok": "th-TH", 496 | "Asia/Jakarta": "id-ID", 497 | "Asia/Dubai": "ar-AE", 498 | "Asia/Taipei": "zh-TW", 499 | 500 | // Australia & Oceania 501 | "Australia/Sydney": "en-AU", 502 | "Australia/Melbourne": "en-AU", 503 | "Australia/Perth": "en-AU", 504 | "Pacific/Auckland": "en-NZ", 505 | 506 | // South America 507 | "America/Sao_Paulo": "pt-BR", 508 | "America/Buenos_Aires": "es-AR", 509 | "America/Bogota": "es-CO", 510 | "America/Mexico_City": "es-MX", 511 | 512 | // Africa 513 | "Africa/Johannesburg": "en-ZA", 514 | "Africa/Cairo": "ar-EG", 515 | "Africa/Nairobi": "en-KE", 516 | 517 | // Middle East 518 | "Asia/Riyadh": "ar-SA", 519 | "Asia/Tehran": "fa-IR", 520 | "Asia/Jerusalem": "he-IL", 521 | 522 | // Aliases (some European and Pacific examples) 523 | "Europe/Belfast": "en-GB", 524 | "Europe/Guernsey": "en-GB", 525 | "Europe/Isle_of_Man": "en-GB", 526 | "Europe/Jersey": "en-GB", 527 | 528 | "Pacific/Johnston": "en-US", 529 | "Pacific/Samoa": "en-US", 530 | 531 | // UTC fallback 532 | "UTC": "en-US", 533 | }; 534 | 535 | 536 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | 6 | 7 | # Homebridge Enphase Envoy 8 | 9 | [![verified-by-homebridge](https://img.shields.io/badge/homebridge-verified-purple)](https://github.com/homebridge/homebridge/wiki/Verified-Plugins) 10 | [![npm](https://shields.io/npm/dt/homebridge-enphase-envoy?color=purple)](https://www.npmjs.com/package/homebridge-enphase-envoy) 11 | [![npm](https://shields.io/npm/v/homebridge-enphase-envoy?color=purple)](https://www.npmjs.com/package/homebridge-enphase-envoy) 12 | [![npm](https://img.shields.io/npm/v/homebridge-enphase-envoy/beta.svg?style=flat-square)](https://www.npmjs.com/package/homebridge-enphase-envoy) 13 | [![GitHub pull requests](https://img.shields.io/github/issues-pr/grzegorz914/homebridge-enphase-envoy.svg)](https://github.com/grzegorz914/homebridge-enphase-envoy/pulls) 14 | [![GitHub issues](https://img.shields.io/github/issues/grzegorz914/homebridge-enphase-envoy.svg)](https://github.com/grzegorz914/homebridge-enphase-envoy/issues) 15 | 16 | 17 | 18 | ## About The Plugin 19 | 20 | The `homebridge-enphase-envoy` plugin integrates Enphase Envoy solar energy monitoring systems with Homebridge, allowing HomeKit users to track solar production, consumption, and battery status directly in the Apple Home app. With real-time energy insights, automation possibilities, and Siri voice control, this plugin enhances smart home energy management by seamlessly connecting your Enphase Envoy system to the HomeKit ecosystem. 21 | 22 | ## Requirements 23 | 24 | | Package | Installation | Role | Required | 25 | | --- | --- | --- | --- | 26 | | [Homebridge v2.0.0](https://github.com/homebridge/homebridge) | [Homebridge Wiki](https://github.com/homebridge/homebridge/wiki) | HomeKit Bridge | Required | 27 | | [Homebridge UI <= v5.5.0](https://github.com/homebridge/homebridge-config-ui-x) | [Homebridge UI Wiki](https://github.com/homebridge/homebridge-config-ui-x/wiki) | Homebridge Web User Interface | Required | 28 | | [Enphase Envoy](https://www.npmjs.com/package/homebridge-enphase-envoy) | [Plug-In Wiki](https://github.com/grzegorz914/homebridge-enphase-envoy/wiki) | Homebridge Plug-In | Required | 29 | 30 | ## Supported hardware 31 | 32 | * Firmware v5 through v8 33 | * System/Enpower `Envoy S`, `IQ Gateway`, `IQ Load Controller`, `IQ Combiner Controller` 34 | * Q-Relays `Q-Relay 1P` `Q-Relay 3P` 35 | * AC Batteries `AC Battery` 36 | * Meters `Production`, `Consumption`, `Storage`, `Back Feed`, `EV Charger`, `PV 3P`, `Load` 37 | * Microinverters `M215`, `M250`, `IQ6`, `IQ7`, `IQ8` 38 | * Encharges `IQ Battery 3`, `IQ Battery 10`, `IQ Battery 5P`, `IQ Battery 3T`, `IQ Battery 10T`, `IQ Battery 10C` 39 | * WirelessKit `Communications Kit 1/2` 40 | * Generator 41 | 42 | ## Exposed accessories in the Apple Home app 43 | 44 | ### Monitoring Sensors 45 | 46 | * System `Data Refresh` 47 | * Production `State`, `Power State`, `Power Level`, `Energy State`, `Energy Level`, `Current`, `Voltage`, `Frequency`, `Power Factor` 48 | * Consumption `Power State`, `Power Level`, `Energy State`, `Energy Level`, `Current`, `Voltage`, `Frequency`, `Power Factor` 49 | * Q-Relay `State` 50 | * Enpower `Grid State` 51 | * Encharge: `State`, `Grid State`, `Backup Level`, `Dry Contacts` 52 | * Solar `Grid State` 53 | * Encharge Profile: `Self Consumption`, `Savings`, `Economy`, `Full Backup` 54 | * Grid: 55 | * Mode: 56 | * Enpower `Grid On`, `Grid Off`, `Multimode Grid On`, `Multimode Grid Off`, `Grid Tied`, `Grid Forming` 57 | * Encharge `Grid On`, `Grid Off`, `Multimode Grid On`, `Multimode Grid Off`, `Grid Tied`, `Grid Forming` 58 | * Solar `Grid On`, `Grid Off`, `Multimode Grid On`, `Multimode Grid Off`, `Grid Tied`, `Grid Forming` 59 | * Quality: 60 | * Production `Current (A)`, `Voltage (V)`, `Power Factor (cos Fi)`, `Frequency (Hz)` 61 | * Consumption Total `Current (A)`, `Voltage (V)`, `Power Factor (cos Fi)`, `Frequency (Hz)`, 62 | * Consumption Net `Current (A)`, `Voltage (V)`, `Power Factor (cos Fi)`, `Frequency (Hz)`, 63 | * Generator `State`, `Mode` 64 | 65 | ### Control Switches, Outlets, Lightbulbs 66 | 67 | * System `Data Refresh`, `Lock Control` 68 | * Production `State`, `Power Mode`, `Power State`, `Power Level` 69 | * AC Battery `Energy State`, `Backup Level Summary`, `Backup Level` 70 | * Enpower `Grid State`, `Dry Contacts` 71 | * Encharge `Energy State Summary`, `Backup Level Summary`, `Energy State`, `Backup Level` 72 | * Encharge Profile 73 | * Self Consumption `Activate`, `Set Reserve` 74 | * Savings `Activate`, `Set Reserve` 75 | * Economy `Activate`, `Set Reserve` 76 | * Full Backup `Activate` 77 | * Generator `State`, `Mode` 78 | * PLC Level `State` 79 | 80 | ## Notes 81 | 82 | * Token authentication (v7.0+) - Tokens can be generated automatically with the Enlighten username (email address) and password or external tools. Tokens generated with Enlighten credentials are automatically refreshed while those generated with external tools are not. 83 | * Envoy `password` is detected automatically or can be added in the configuration if already changed by user. 84 | * Installer `password` is generated automatically (firmware < v7.0+). 85 | * Envoy `device ID` is detected automatically. 86 | * Supports [Production State Conrol](https://github.com/grzegorz914/homebridge-enphase-envoy/wiki#power-production-control) and `PLC Level Check` (firmware v7.0+ requires installer credentials). 87 | * For the best experience and to display all data, please use the `Controller` or `Eve` apps. 88 | * External integrations include: [REST](https://github.com/grzegorz914/homebridge-enphase-envoy?tab=readme-ov-file#restful-integration) and [MQTT](https://github.com/grzegorz914/homebridge-enphase-envoy?tab=readme-ov-file#mqtt-integration). 89 | 90 | ### Configuration 91 | 92 | * Running this plugin as a [Child Bridge](https://github.com/homebridge/homebridge/wiki/Child-Bridges) is **highly recommended**. This prevents Homebridge from crashing if the plugin crashes. 93 | * Installation and use of [Homebridge UI <= v5.5.0](https://github.com/homebridge/homebridge-config-ui-x) to configure this plugin. 94 | * The `sample-config.json` can be edited and used as an alternative for advanced users. 95 | 96 |

97 | 98 |

99 | 100 | | Key | Subkey | Type | Description | 101 | | --- | --- | --- | --- | 102 | | `name` | | string | Envoy Enphase Gateway accessory name to be displayed in Home app | 103 | | `host` | | string | The Envoy Enphase Gateway `IP Address` or `Hostname`. If not supplied, defaults to `envoy.local`. For firmware v7.0+, please set the `IP Address`. | 104 | | `displayType` | | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Light Bulb, `2` - Fan, `3` - Humidity Sensor, `4` - Carbon Monoxide Sensor | 105 | | `envoyFirmware7xxTokenGenerationMode` | | number | How you will obtain the token: `0` - Envoy Password (firmware < v7.0), `1` - Enlighten Credentials, `2` - Your Own Generated Token | 106 | | `envoyPasswd` | | string | Envoy password (only if U already changed the default password) || 107 | | `enlightenUser` | | string | Enlighten username | 108 | | `enlightenPasswd` | | string | Enlighten password | 109 | | `envoyToken` | | string | Token if you selected `2 - Your Own Generated Token` for envoyFirmware7xxTokenGenerationMode | 110 | | `envoyTokenInstaller` | | boolean | Enable if you are using the installer token | 111 | | `lockControl` | | key | `Lock Control` for enable?disable system control | 112 | | | `lockControl.enable` | boolean | Enables system control auto lock accessory | 113 | | | `lockControl.time` | number | `System Auto Lock Control` time (seconds) | 114 | | | `lockControl.namePrefix` | boolean | Use accessory name for prefix | 115 | | `energyMeter` | | boolean | Enables energy meter as a axtra accessory to display charts in EVE app | 116 | | `productionStateSensor` | | key | `Production State Sensor` for production state monitoring | 117 | | | `name` | string | Accessory name for Home app | 118 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 119 | | | `namePrefix` | boolean | Use accessory name for prefix | 120 | | `plcLevelControl` | | key | `PLC Level Control` for PLC level check (firmware v7.0+ require installer credentials) | 121 | | | `name` | string | Accessory name for Home app | 122 | | | `displayType` | number | Accessory type for Home app: `0` - None/Disabled, `1` - Switch, `2` - Outlet, `3` - Lightbulb | 123 | | | `namePrefix` | boolean | Use accessory name for prefix | 124 | | `powerProductionSummary` | | number | `Power Summary`, in `W`, of all microinverters. This will be used to calculate the display power level in the Home app `0-100 %` | 125 | | `powerProductionLevelSensors` | | key | `Power Level Sensor` for production monitoring | 126 | | | `name` | string | Accessory name for Home app | 127 | | | `compareMode` | string | Comparison mode: `<`, `<=`, `==`, `>`, `>=`, `!=` | 128 | | | `powerLevel` | number | Power production level in `W` to compare to sensor that was triggered | 129 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 130 | | | `namePrefix` | boolean | Use accessory name for prefix | 131 | | `energyProductionLifetimeOffset` | | number | `Energy Offset` in `Wh` for production (if needed) `+/-` | 132 | | `energyProductionLevelSensors` | | key | `Energy Level Sensor` for production monitoring | 133 | | | `name` | string | Accessory name for Home app | 134 | | | `compareMode` | string | Comparison mode: `<`, `<=`, `==`, `>`, `>=`, `!=` | 135 | | | `energyLevel` | number | Energy production level in `Wh` to compare to sensor that was triggered | 136 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 137 | | | `namePrefix` | boolean | Use accessory name for prefix | 138 | | `gridProductionQualitySensors` | | key | `Power Level Sensor` for production monitoring | 139 | | | `name` | string | Accessory name for Home app | 140 | | | `compareMode` | string | Comparison mode: `<`, `<=`, `==`, `>`, `>=`, `!=` | 141 | | | `compareType` | string | Comparison type: `Current`, `Voltage`, `Frequency`, `Power Factor` | 142 | | | `compareLevel` | number | Level to compare to sensor that was triggered | 143 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 144 | | | `namePrefix` | boolean | Use accessory name for prefix | 145 | | `powerConsumptionTotalLevelSensors` | | key | `Power Level Sensor` for total consumption monitoring | 146 | | | `name` | string | Accessory name for Home app | 147 | | | `compareMode` | string | Comparison mode `<`, `<=`, `==`, `>`, `>=`, `!=` | 148 | | | `powerLevel` | number | Total power consumption level in `W` to compare to power level sensor that was triggered | 149 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 150 | | | `namePrefix` | boolean | Use accessory name for prefix | 151 | | `energyConsumptionTotalLifetimeOffset` | | number | `Energy Offset` in `Wh` for total consumption (if needed) `+/-` | 152 | | `energyConsumptionTotalLevelSensors` | | key | `Energy Level Sensor` for total consumption monitoring | 153 | | | `name` | string | Accessory name for Home app | 154 | | | `compareMode` | string | Comparison mode `<`, `<=`, `==`, `>`, `>=`, `!=` | 155 | | | `energyLevel` | number | Energy level total in `Wh` to compare to sensor that was triggered | 156 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 157 | | | `namePrefix` | boolean | Use accessory name for prefix | 158 | | `gridConsumptionTotalQualitySensors` | | key | `Power Level Sensor` for production monitoring | 159 | | | `name` | string | Accessory name for Home app | 160 | | | `compareMode` | string | Comparison mode: `<`, `<=`, `==`, `>`, `>=`, `!=` | 161 | | | `compareType` | string | Comparison type: `Current`, `Voltage`, `Frequency`, `Power Factor` | 162 | | | `compareLevel` | number | Level to compare to sensor that was triggered | 163 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 164 | | | `namePrefix` | boolean | Use accessory name for prefix | 165 | | `powerConsumptionNetLevelSensors` | | key | `Power Level Sensor` for net power consumption level monitoring | 166 | | | `name` | string | Accessory name for Home app | 167 | | | `compareMode` | string | Comparison mode `<`, `<=`, `==`, `>`, `>=`, `!=` | 168 | | | `powerLevel` | number | Net power consumption power level in `W` to compare for the sensor that was triggered | 169 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 170 | | | `namePrefix` | boolean | Use accessory name for prefix | 171 | | `energyConsumptionNetLifetimeOffset` | | number | `Energy Offset` in `Wh` for consumption `Net` (if needed) `+/-` | 172 | | `energyConsumptionNetLevelSensors` | | key | `Energy Level Sensor` for net consumption monitoring | 173 | | | `name` | string | Accessory name for Home app | 174 | | | `compareMode` | string | Comparison mode `<`, `<=`, `==`, `>`, `>=`, `!=` | 175 | | | `energyLevel` | number | Net energy comsumption level in `Wh` to compare to sensor that was triggered | 176 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 177 | | | `namePrefix` | boolean | Use accessory name for prefix | 178 | | `gridConsumptionNetQualitySensors` | | key | `Power Level Sensor` for production monitoring | 179 | | | `name` | string | Accessory name for Home app | 180 | | | `compareMode` | string | Comparison mode: `<`, `<=`, `==`, `>`, `>=`, `!=` | 181 | | | `compareType` | string | Comparison type: `Current`, `Voltage`, `Frequency`, `Power Factor` | 182 | | | `compareLevel` | number | Level to compare to sensor that was triggered | 183 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 184 | | | `namePrefix` | boolean | Use accessory name for prefix | 185 | | `qRelayStateSensor` | | key | `Q-Relay State Sensor` for monitoring. If `State ON`, the contact was opened. | 186 | | | `name` | string | Accessory name for Home app | 187 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 188 | | | `namePrefix` | boolean | Use accessory name for prefix | 189 | | | `multiphase` | boolean | Enables multiphase support, if present | 190 | | `acBatterieName` | | string | AC Bettery Accessory name for Home app, if not set will use default name | 191 | | `acBatterieBackupLevelSummaryAccessory` | | key | `AC Batteries Backup Level Summary Accessory` in Home app, if present | 192 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Light Bulb, `2` - Fan, `3` - Humidity Sensor, `4` - Carbon Monoxide Sensor, `5` - Battery | 193 | | | `minSoc` | boolean | Minimum SoC level in (%) for ac batteries backup level summary | 194 | | `acBatterieBackupLevelAccessory` | | key | `AC Battery Backup Level Accessory` in Home app, if present | 195 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Light Bulb, `2` - Fan, `3` - Humidity Sensor, `4` - Carbon Monoxide Sensor, `5` - Battery | 196 | | | `minSoc` | boolean | Minimum SoC level in (%) for ac battery backup level | 197 | | `enpowerGridStateControl` | | key | `Enpower Grid State Control` for `Grid ON/OFF` control from HomeKit | 198 | | | `name` | string | Accessory name for Home app | 199 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Switch, `2` - Outlet, `3` - Lightbulb | 200 | | | `namePrefix` | boolean | Use accessory name for prefix | 201 | | `enepowerGridStateSensor` | | key | `Enpower Grid State Sensor` for monitoring. If `Grid ON`, the contact was opened. | 202 | | | `name` | string | Accessory name for Home app | 203 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 204 | | | `namePrefix` | boolean | Use accessory name for prefix | 205 | | `enpowerGridModeSensors` | | key | `Enpower Grid Mode Sensors` for monitoring. If the `Mode` matches, the contact was opened. | 206 | | | `name` | string | Accessory name for Home app | 207 | | | `gridMode` | string | Grid mode: `Grid On`, `Grid Off`, `Multimode Grid On`, `Multimode Grid Off`, `Grid Tied`, `Grid Forming` | 208 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 209 | | | `namePrefix` | boolean | Use accessory name for prefix | 210 | | `enchargeName` | | string | Encharge Accessory name for Home app, if not set will use default name | 211 | | `enchargeBackupLevelSummaryAccessory` | | key | `Encharge Backup Level Summary Accessory` in Home app, if present | 212 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Light Bulb, `2` - Fan, `3` - Humidity Sensor, `4` - Carbon Monoxide Sensor, `5` - Battery | 213 | | | `minSoc` | boolean | Minimum SoC level in (%) for encharges backup level summary | 214 | | `enchargeBackupLevelAccessory` | | key | `Encharge Backup Level Accessory` in Home app, if present | 215 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, , `1` - Battery | 216 | | | `minSoc` | boolean | Minimum SoC level in (%) for encharges backup level summary | 217 | | `enchargeStateSensor` | | key | `Encharge State Sensor` for monitoring. If `State ON`, the contact was opened. | 218 | | | `name` | string | Accessory name for Home app | 219 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 220 | | | `namePrefix` | boolean | Use accessory name for prefix | 221 | | `enchargeProfileControls` | | key | `Encharge Profile Controls` for `Profile` control from HomeKit | 222 | | | `name` | string | Accessory name for Home app | 223 | | | `profile` | string | Profile: `Savings`, `Economy`, `Full Backup`, `Self Consumption` | 224 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Lightbulb | 225 | | | `chargeFromGrid` | boolean | Allow charge from grid | 226 | | | `namePrefix` | boolean | Use accessory name for prefix | 227 | | `enchargeProfileSensors` | | key | `Encharge Profile Sensors` for monitoring. If the `Profile` matches, the contact was opened. | 228 | | | `name` | string | Accessory name for Home app | 229 | | | `profile` | string | Profile: `Savings`, `Economy`, `Full Backup`, `Self Consumption` | 230 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 231 | | | `namePrefix` | boolean | Use accessory name for prefix | 232 | | `enechargeGridStateSensor` | | key | `Encharge Grid State Sensor` for monitoring. If `Grid ON`, the contact was opened. | 233 | | | `name` | string | Accessory name for Home app | 234 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 235 | | | `namePrefix` | boolean | Use accessory name for prefix | 236 | | `enchargeGridModeSensors` | | key | `Encharge Grid Mode Sensors` for monitoring. If the `Mode` matches, the contact was opened. | 237 | | | `name` | string | Accessory name for Home app | 238 | | | `gridMode` | string | Grid mode: `Multimode Grid On`, `Multimode Grid Off` | 239 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 240 | | | `namePrefix` | boolean | Use accessory name for prefix | 241 | | `enchargeBackupLevelSensors` | | key | `Encharge Backup Level Sensors` for monitoring. If the `Level` matches, the contact was opened. | 242 | | | `name` | string | Accessory name for Home app | 243 | | | `compareMode` | string | Comparison mode: `<`, `<=`, `==`, `>`, `>=` | 244 | | | `backupLevel` | number | Backup level in `%` to compare to sensor that was triggered | 245 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 246 | | | `namePrefix` | boolean | Use accessory name for prefix | 247 | | `solarGridStateSensor` | | key | `Solar Grid State Sensor` for monitoring. If `Grid ON`, the contact was opened. | 248 | | | `name` | string | Accessory name for Home app | 249 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 250 | | | `namePrefix` | boolean | Use accessory name for prefix | 251 | | `solarGridModeSensors` | | key | `Solar Grid Mode Sensors` for monitoring. If the `Mode` matches, the contact was opened. | 252 | | | `name` | string | Accessory name for Home app | 253 | | | `gridMode` | string | Grid mode: `Grid On`, `Grid Off`, `Multimode Grid On`, `Multimode Grid Off`, `Grid Tied`, `Grid Forming` | 254 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 255 | | | `namePrefix` | boolean | Use accessory name for prefix | 256 | | `enpowerDryContactsControl` | | boolean | Enables `Dry Contacts` control and exposes `Switches` in Home app | 257 | | `enpowerDryContactsSensor` | | boolean | Enables `Dry Contacts` monitoring and exposes `Sensors` in Home app | 258 | | `generatorStateControl` | | key | `Generator State Control` for `Generator OFF/ON` control in Home app | 259 | | | `name` | string | Accessory name for Home app | 260 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Switch, `2` - Outlet, `3` - Lightbulb | 261 | | | `namePrefix` | boolean | Use accessory name for prefix | 262 | | `generatorStateSensor` | | key | `Generator State Sensor` for `State` monitoring. If `State not Off`, the contact was opened. | 263 | | | `name` | string | Accessory name for Home app | 264 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 265 | | | `namePrefix` | boolean | Use accessory name for prefix | 266 | | `generatorModeContol` | | key | `Generator Mode Control`, for `Generator OFF/ON/AUTO` control in Home app | 267 | | | `name` | string | Accessory name for Home app | 268 | | | `mode` | string | Grid mode: `Off`, `On`, `Auto` | 269 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Switch, `2` - Outlet, `3` - Lightbulb | 270 | | `generatorModeSensors` | | key | `Generator Mode Sensors` for monitoring, if the `Mode` matches, the contact was opened. | 271 | | | `name` | string | Accessory name for Home app | 272 | | | `mode` | string | Grid mode: `Off`, `On`, `Auto` | 273 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 274 | | | `namePrefix` | boolean | Use accessory name for prefix | 275 | | `acBatterieBackupLevelAccessory` | | key | `AC Battery Backup Level Accessory` in Home app, if present | 276 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, , `1` - Battery | 277 | | | `minSoc` | boolean | Minimum SoC level in (%) for ac battery backup level summary | 278 | | `dataRefreshControl` | | key | `Data Refresh Control` from HomeKit. | 279 | | | `name` | string | Accessory name for Home app | 280 | | | `displayType` | number | Here select the tile type to be displayed in Home app: `0` - None/Disabled, `1` - Switch, `2` - Outlet, `3` - Lightbulb | 281 | | | `namePrefix` | boolean | Use accessory name for prefix | 282 | | `dataRefreshSensor` | | key | `Data Refresh Sensor` for monitoring. If operating, the contact was opened. | 283 | | | `name` | string | Accessory name for Home app | 284 | | | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor | 285 | | | `namePrefix` | boolean | Use accessory name for prefix | 286 | | `productionDataRefreshTime` | | number | `Production Data` refresh time (seconds) | 287 | | `liveDataRefreshTime` | | number | `Live Data` refresh time (seconds) | 288 | | `ensembleDataRefreshTime` | | number | `Ensemble Data` refresh time (seconds) | 289 | | `log` | | key | `Log` from HomeKit. | 290 | | | `deviceInfo` | boolean | If enabled, log device info will be displayed by every connections device to the network. | 291 | | | `success` | boolean | If enabled, success log will be displayed in console. | 292 | | | `info` | boolean | If enabled, info log will be displayed in console. | 293 | | | `warn` | boolean | If enabled, warn log will be displayed in console. | 294 | | | `error` | boolean | If enabled, error log will be displayed in console. | 295 | | | `debug` | boolean | If enabled, debug log will be displayed in console. | 296 | | `restFul` | | key | REST service | 297 | | | `enable` | boolean | Enables REST service to start automatically and respond to any request | 298 | | | `port` | number | `Port` for REST service | 299 | | `mqtt` | | key | MQTT broker | 300 | | | `enable` | boolean | Enables MQTT broker to start automatically and publish available data | 301 | | | `host` | string | `IP Address` or `Hostname` for MQTT Broker | 302 | | | `port` | number | `Port` for MQTT broker (default to 1883) | 303 | | | `clientId` | string | `Client Id` of MQTT broker (optional) | 304 | | | `prefix` | string | `Prefix` for `Topic` (optional) | 305 | | | `auth` | boolean | Enables MQTT broker authorization credentials | 306 | | | `user` | string | MQTT broker user | 307 | | | `passwd` | string | MQTT Broker password | 308 | 309 | ### REST Integration 310 | 311 | REST POST calls must include a content-type header of `application/json`. 312 | Path `status` response all available paths. 313 | 314 | | Method | URL | Path | Response | Type | 315 | | --- | --- | --- | --- | --- | 316 | | GET | `http//ip:port` | `token`, `info`, `home`, `homedata`, `inventory`, `microinvertersstatus`, `meters`, `metersreading`, `metersreports`, `detaileddevicesdata`, `microinvertersdata`, `qrelaysdata`, `metersdata`, `production`, `productionpdm`, `energypdm`, `productionct`,`powerandenergydata`, `acbatterydata`, `ensembleinventory`, `ensemblestatus`, `ensemblepower`, `enchargesettings`, `tariff`, `drycontacts`, `drycontactssettings`, `generator`, `generatorsettings`, `ensembledata`, `gridprofile`, `livedata`, `livedatadata`, `productionstate`, `plclevel`, `datasampling`. | `{wNow: 2353}` | JSON | 317 | 318 | | Method | URL | Key | Value | Type | Description | 319 | | --- | --- | --- | --- | --- | --- | 320 | | POST | `http//ip:port` | `DataSampling` | `true`, `false` | boolean | Data sampling Start/Stop | 321 | | | `http//ip:port` | `PowerProductionState` | `true`, `false` | boolean | Production state On/Off | 322 | | | `http//ip:port` | `PlcLevel` | `true` | boolean | Check Plc Level On | 323 | | | `http//ip:port` | `EnchargeProfile` | `self-consumption`, `savings-mode`, `economy`, `backup` | string | Set encharge profile | 324 | | | `http//ip:port` | `EnchargeReservedSoc` | `0-100` | number | Set encharge reserve SoC 0-100% | 325 | | | `http//ip:port` | `EnchargeChargeFromGrid` | `true`, `false` | boolean | Set encharge charge from grid On/Off | 326 | | | `http//ip:port` | `EnpowerGridState` | `true`, `false` | boolean | Grid state On/Off | 327 | | | `http//ip:port` | `GeneratorMode` | `off`, `on`, `auto` | string | Generator mode Off/On/Auto | 328 | 329 | ### MQTT Integration 330 | 331 | Subscribe using JSON `{ "EnchargeProfile": "savings" }` 332 | 333 | | Method | Topic | Message | Type | 334 | | --- | --- | --- | --- | 335 | | Publish | `Token`, `Info`, `Home`, `Home Data`, `Inventory`, `Microinverters Status`, `Meters`, `Meters Reading`, `Meters Reports`, `Detailed Devices Data`, `Microinverters Data`, `Q-Relays Data`, `Meters Data`, `Production`, `Production Pdm`, `Energy Pdm`, `Production CT`, `Power And Energy Data`, `AC Battery Data`, `Ensemble Inventory`, `Ensemble Status`, `Ensemble Status`, `Encharge Power`, `Tariff`, `Dry Contacts`, `Dry Contacts Settings`, `Generator`, `Generator Settings`, `Ensemble Data`, `Grid Profile`, `Live Data`, `Live Data Data`, `Production State`, `PLC Level`, `Data Sampling` | `{wNow: 2353}` | JSON | 336 | 337 | | Method | Topic | Key | Value | Type | Description | 338 | | --- | --- | --- | --- | --- | --- | 339 | | Subscribe | `Set` | `DataSampling` | `true`, `false` | boolean | Data sampling Start/Stop | 340 | | | `Set` | `ProductionState` | `true`, `false` | boolean | Production state On/Off | 341 | | | `Set` | `PlcLevel` | `true` | boolean | Check Plc Level On | 342 | | | `Set` | `EnchargeProfile` | `self-consumption`, `savings-mode`, `economy`, `backup` | string | Set encharge profile | 343 | | | `Set` | `EnchargeReservedSoc` | `0-100` | number | Set encharge reserve SoC 0-100% | 344 | | | `Set` | `EnchargeChargeFromGrid` | `true`, `false` | boolean | Set encharge charge from grid On/Off | 345 | | | `Set` | `EnpowerGridState` | `true`, `false` | boolean | Grid state On/Off | 346 | | | `Set` | `GeneratorMode` | `off`, `on`, `auto` | string | Generator mode Off/On/Auto | 347 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## Note 9 | 10 | - after update to v10.0.0 and above the accessory and bridge need to be removed from the homebridge / Home.app and added again 11 | 12 | ## [10.3.8] - (17.12.2025) 13 | 14 | ## Changes 15 | 16 | - fix [#222](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/222) 17 | - bump dependencies 18 | 19 | ## [10.3.7] - (09.12.2025) 20 | 21 | ## Changes 22 | 23 | - moved MQTT to v5 24 | - cleanup 25 | 26 | ## [10.3.5] - (13.11.2025) 27 | 28 | ## Changes 29 | 30 | - added encharges support connected to all phases 31 | - cleanup 32 | 33 | ## [10.3.4] - (12.11.2025) 34 | 35 | ## Changes 36 | 37 | - fix [#221](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/221) 38 | - bump dependencies 39 | - cleanup 40 | 41 | ## [10.3.2] - (30.10.2025) 42 | 43 | ## Changes 44 | 45 | - fix [#220](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/220) 46 | 47 | ## [10.3.1] - (29.10.2025) 48 | 49 | ## Changes 50 | 51 | - bump dependencies 52 | - redme updated 53 | - cleanup 54 | 55 | ## [10.3.0] - (20.10.2025) 56 | 57 | ## Changes 58 | 59 | - extend Eve Energy Meter to support (Production, Consumption Net, Consumption Total) 60 | - fix [#218](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/218) 61 | - stability and performance improvements 62 | - config schema updated 63 | - readme updated 64 | - cleanup 65 | 66 | ## [10.2.6] - (18.10.2025) 67 | 68 | ## Changes 69 | 70 | - fix [#216](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/216) 71 | - fix [#217](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/217) 72 | - fix wireless connections kit publish 73 | - added network interface service and characteristics 74 | - cleanup 75 | 76 | ## [10.2.5] - (17.10.2025) 77 | 78 | ## Changes 79 | 80 | - update EVE Energy Meter 81 | - cleanup 82 | 83 | ## [10.2.3] - (15.10.2025) 84 | 85 | ## Changes 86 | 87 | - fix [#215](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/215) 88 | - update EVE Energy Meter 89 | - other small fixes 90 | - cleanup 91 | 92 | ## [10.2.2] - (12.10.2025) 93 | 94 | ## Changes 95 | 96 | - fix power level not refresh if meter production not enabled [#213](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/213) 97 | - fix enable live data stream [#214](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/214) 98 | - changed OFF state to < 0.5% for power and backup level accessory, before was OFF if level < 1% 99 | - stability and performance improvements 100 | - other small fixes 101 | - redme updates 102 | - cleanup 103 | 104 | ## [10.2.1] - (03.10.2025) 105 | 106 | ## Changes 107 | 108 | - fix power level not refresh if meter production not enabled [#213](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/213) 109 | 110 | ## [10.2.0] - (03.10.2025) 111 | 112 | ## Changes 113 | 114 | - fix encharge profile control UI interface 115 | - fix [#205](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/205) 116 | - fix [#206](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/206) 117 | - fix [#207](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/207) 118 | - fix [#209](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/209) 119 | - fix [#211](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/211) 120 | - workaround for [#210](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/210), envoy firmware issue 121 | - prepare to add encharge profile controls option to allow charge from grid 122 | - added configurable system auto lock time 123 | - added EVE energy monitor option (need to be paired as a separate accessory) 124 | - added support for EVSE, PV3P, BackFeed meters 125 | - added support for C6 Combiner Controller, C6 RGM, IQ Meter Collar 126 | - refactor code of ensemble section 127 | - stability and improvements 128 | - config UI updated 129 | - bump dependencies 130 | - redme updated 131 | - cleanup 132 | 133 | ## [10.1.0] - (01.07.2025) 134 | 135 | ## Changes 136 | 137 | - fix update plc level for microinverters 138 | - added lockcontrol system for envoy section 139 | 140 | ## [10.0.3] - (29.06.2025) 141 | 142 | ## Changes 143 | 144 | - fix scale plc level to 100% 145 | 146 | ## [10.0.2] - (29.06.2025) 147 | 148 | ## Changes 149 | 150 | - fix generator mode 151 | - changed RESTFul path `powermode` to `productionstate` 152 | - changed MQTT set key `PowerProductionState` to `ProductionState` 153 | - stability and performance improvements 154 | - redme updated 155 | - cleanup 156 | 157 | ## [10.0.1] - (25.06.2025) 158 | 159 | ## Changes 160 | 161 | - fix RESTFul `detaileddevicesdata` and `token` paths 162 | - fix Mqtt `token` refresh 163 | - redme updated 164 | 165 | ## [10.0.0] - (24.06.2025) 166 | 167 | ## Changes 168 | 169 | - full code refactor 170 | - stability and performance improvements 171 | - added many detailed data for microinverters, meters, qrelays 172 | - RESTFul code refactor and updated 173 | - cleanup custom characteristics 174 | - cleanup 175 | - readme updated 176 | - many more small changes 177 | 178 | ## [9.20.1] - (15.06.2025) 179 | 180 | ## Changes 181 | 182 | - fix [#202](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/202) 183 | - cleanup 184 | 185 | ## [9.20.0] - (14.06.2025) 186 | 187 | ## Changes 188 | 189 | - stability and performance improvements 190 | - added devicesdata, metersRportsto to the RESTFul rquests 191 | - added Energy and Productin Consumption Total service if present 192 | - added energyLifetimeUpload characteristic for Production(mean self consumption) and Consumption Net(mean upload to the grid) 193 | - added node.js 24 support 194 | - bump dependencies 195 | - redme updated 196 | - cleanup 197 | 198 | ## [9.19.0] - (04.06.2025) 199 | 200 | ## Changes 201 | 202 | - added microinverters additional data (voltage, frequency, temperature, energy today, yesterday, last seven days, lifetime) 203 | - redme updated 204 | - cleanup 205 | 206 | ## [9.18.0] - (30.05.2025) 207 | 208 | ## Changes 209 | 210 | - removed extra production control accessory 211 | - added production control in the main lightbulb accessory 212 | - added control lock accessory to prevent device control accidentially 213 | - device control possible after unlock 214 | - locked automatically 30sec after unlock 215 | - config UI updated 216 | - redme updated 217 | - cleanup 218 | 219 | ## [9.17.7] - (28.05.2025) 220 | 221 | ## Changes 222 | 223 | - stability and performance improvements 224 | - cleanup 225 | 226 | ## [9.17.5] - (27.05.2025) 227 | 228 | ## Changes 229 | 230 | - prevent update meters characteristics if value are not valid 231 | 232 | ## [9.17.4] - (27.05.2025) 233 | 234 | ## Changes 235 | 236 | - fix voltage divide 237 | - cleanup 238 | 239 | ## [9.17.3] - (27.05.2025) 240 | 241 | ## Changes 242 | 243 | - fix power peak update characteristics 244 | - cleanup 245 | 246 | ## [9.17.2] - (26.05.2025) 247 | 248 | ## Changes 249 | 250 | - cleanup 251 | 252 | ## [9.17.1] - (26.05.2025) 253 | 254 | ## Changes 255 | 256 | - fix [#199](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/199) 257 | 258 | ## [9.17.0] - (26.05.2025) 259 | 260 | ## Changes 261 | 262 | - removed duplicated power and energy state sensors, the state sensor can be create by level sensors > 0 263 | - removed meters refresh time 264 | - fix consumption power peak detected 265 | - refactor production all code 266 | - refsctor charcteristics update 267 | - added conparator (!==) to sensors 268 | - config UI improvements 269 | - mqtt clientId and prefix updated 270 | - redme update 271 | - cleanup 272 | 273 | ## [9.16.0] - (21.05.2025) 274 | 275 | ## Changes 276 | 277 | - added grid quality sensors for(Current, Voltage, Frequency, Power Factor) if meters are installed 278 | - fix qRelay state update 279 | - redme update 280 | - cleanup 281 | 282 | ## [9.15.0] - (18.05.2025) 283 | 284 | ## Changes 285 | 286 | - fix [#198](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/198) 287 | - refactor code of production and consumption data update (support fw. >= 8.2.4xx) 288 | - bump dependencies 289 | - redme update 290 | - cleanup 291 | 292 | ## [9.14.6] - (12.05.2025) 293 | 294 | ## Changes 295 | 296 | - fix [#197](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/197) 297 | - bump dependencies 298 | 299 | ## [9.14.4] - (09.05.2025) 300 | 301 | ## Changes 302 | 303 | - fix read meters reading with envoy firmware 8.3.xx 304 | - better handle some errors/warn 305 | - bump dependencies 306 | - cleanup 307 | 308 | ## [9.14.3] - (20.04.2025) 309 | 310 | ## Changes 311 | 312 | - fix [#195](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/195) 313 | - fix [#196](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/196) 314 | - cleanup 315 | 316 | ## [9.14.2] - (20.04.2025) 317 | 318 | ## Changes 319 | 320 | - many cleanup and optimizations 321 | - cleanup 322 | 323 | ## [9.14.1] - (18.04.2025) 324 | 325 | ## Changes 326 | 327 | - fix namePrefix and call production state even not supported 328 | 329 | ## [9.14.0] - (18.04.2025) 330 | 331 | ## Changes 332 | 333 | - added multiphase support for q-relay sensor 334 | - digestauth refactor 335 | - passwdcalc refactor 336 | - envoytoken refactor 337 | - redme update 338 | - cleanup 339 | 340 | ## [9.13.4] - (18.04.2025) 341 | 342 | ## Changes 343 | 344 | - fix power peak level display and detected in consumption total and net 345 | - cleanup 346 | 347 | ## [9.13.3] - (18.04.2025) 348 | 349 | ## Changes 350 | 351 | - fix reference error in debug mode 352 | - cleanup 353 | 354 | ## [9.13.2] - (17.04.2025) 355 | 356 | ## Changes 357 | 358 | - fix microinverters publish in v9.13.0 and v9.13.1 359 | - refresh grid profile and update status in runtime 360 | - display in envoy db size and percent full of db only if supported 361 | - display update status in envoy only if supported 362 | - stability and performance optimizations 363 | - cleanup 364 | 365 | ## [9.13.1] - (16.04.2025) 366 | 367 | ## Changes 368 | 369 | - RESTFul and MQTT update 370 | - stability and performance optimizations 371 | - redme update 372 | - cleanup 373 | 374 | ## [9.13.0] - (15.04.2025) 375 | 376 | ## Changes 377 | 378 | - added pdm energy and production data to RESTFul and MQTT for Envoy FW >= 8.2.4xx 379 | - removed production all from RESTFul and MQTT 380 | - redme update 381 | - cleanup 382 | 383 | ## [9.12.6] - (08.04.2025) 384 | 385 | ## Changes 386 | 387 | - fix stop data sampling if error occured durig cookie refresh 388 | - fix set correct accessory category 389 | - added production state data refresh timer 390 | - config UI improvements in section Envoy 391 | - config schema updated 392 | - redme update 393 | - cleanup 394 | 395 | ## [9.12.0] - (05.04.2025) 396 | 397 | ## Changes 398 | 399 | - after update the plc level refresh control need to be configued again 400 | - after update the production state control and sensor need to be configued again 401 | - added production state sensor 402 | - config UI improvements in section Envoy 403 | - config schema updated 404 | - bump dependencies 405 | - redme update 406 | - cleanup 407 | 408 | ## [9.11.0] - (03.04.2025) 409 | 410 | ## Changes 411 | 412 | - after update the credentials method need to be configued again 413 | - after update the dry contact sensor and control need to be configued again 414 | - config UI improvements 415 | - config schema updated 416 | - bump dependencies 417 | - redme update 418 | - cleanup 419 | 420 | ## [9.10.9] - (30.03.2025) 421 | 422 | ## Changes 423 | 424 | - fix energyConsumptionNetStateSensor UI 425 | - config schema updated 426 | 427 | ## [9.10.8] - (28.03.2025) 428 | 429 | ## Changes 430 | 431 | - stability and performance improvements 432 | - config schema updated 433 | - cleanup 434 | 435 | ## [9.10.7] - (26.03.2025) 436 | 437 | ## Changes 438 | 439 | - fix [#192](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/192) 440 | 441 | ## [9.10.6] - (26.03.2025) 442 | 443 | ## Changes 444 | 445 | - fix Q-Relay state monitoring sensor 446 | 447 | ## [9.10.5] - (25.03.2025) 448 | 449 | ## Changes 450 | 451 | - added Q-Relay state monitoring sensor 452 | - stability and performance improvements 453 | - config schema updated 454 | - redme updated 455 | - cleanup 456 | 457 | ## [9.10.0] - (23.03.2025) 458 | 459 | ## Changes 460 | 461 | - added possibility to select accessory type for Envoy 462 | - added possibility to select accessory type for AC Battery, indyvidual and summary 463 | - added possibility to select accessory type for Encharge, indyvidual and summary 464 | - added possibility to set min SoC for light bulb Encharge accessory [#191](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/191) 465 | - stability and performance improvements 466 | - config schema updated 467 | - redme updated 468 | - cleanup 469 | 470 | ## [9.9.10] - (21.03.2025) 471 | 472 | ## Changes 473 | 474 | - fix [#190](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/190) 475 | - cleanup 476 | 477 | ## [9.9.9] - (21.03.2025) 478 | 479 | ## Changes 480 | 481 | - fix [#189](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/189) 482 | - cleanup 483 | 484 | ## [9.9.8] - (20.03.2025) 485 | 486 | ## Changes 487 | 488 | - config UI improvements from [#185](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/185) 489 | - config schema updated 490 | 491 | ## [9.9.7] - (20.03.2025) 492 | 493 | ## Changes 494 | 495 | - added possibility to set custom encharge name displayed in the home app, closes [#188](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/188) 496 | - added possibility to disable/display encharge light bulb accessory in the home app 497 | - bump dependencies 498 | - config schema updated 499 | - redme updated 500 | - cleanup 501 | 502 | ## [9.9.4] - (19.03.2025) 503 | 504 | ## Changes 505 | 506 | - fix backup level sensor update [#186](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/186) 507 | - config UI improvements [#185](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/185) 508 | - config schema updated 509 | - cleanup 510 | 511 | ## [9.9.3] - (18.03.2025) 512 | 513 | ## Changes 514 | 515 | - added default values to fix [#183](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/183) 516 | - cleanup 517 | 518 | ## [9.9.2] - (15.03.2025) 519 | 520 | ## Changes 521 | 522 | - fix [#182](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/182) 523 | - cleanup 524 | 525 | ## [9.9.1] - (15.03.2025) 526 | 527 | ## Changes 528 | 529 | - fix [#181](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/181) 530 | - cleanup 531 | 532 | ## [9.9.0] - (14.03.2025) 533 | 534 | ## Changes 535 | 536 | - added possibility to disable indyvidual accessory 537 | - added read production all (pcm, rgm, eim) and consumption (eim) 538 | - fix debug log 539 | - bump dependencies 540 | - config schema updated 541 | - redme updated 542 | - cleanup 543 | 544 | ## [9.8.7] - (04.03.2025) 545 | 546 | ## Changes 547 | 548 | - token handling improvements 549 | - digest installer and envoy handling improvements 550 | - error handling improvements 551 | - cleanup 552 | 553 | ## [9.8.6] - (02.03.2025) 554 | 555 | ## Changes 556 | 557 | - token and cookie handling improvements 558 | - impulse generator corect start state 559 | - cleanup 560 | 561 | ## [9.8.5] - (28.02.2025) 562 | 563 | ## Changes 564 | 565 | - token and digest authorization handling improvements 566 | - bump dependencies 567 | - cleanup 568 | 569 | ## [9.8.4] - (27.02.2025) 570 | 571 | ## Changes 572 | 573 | - token handling improvements 574 | - plugin start time improvements 575 | - cleanup 576 | 577 | ## [9.8.3] - (26.02.2025) 578 | 579 | ## Changes 580 | 581 | - bump dependencies 582 | 583 | ## [9.8.2] - (26.02.2025) 584 | 585 | ## Changes 586 | 587 | - refactor start external integrations 588 | - bump dependencies 589 | - cleanup 590 | 591 | ## [9.8.0] - (20.02.2025) 592 | 593 | ## Changes 594 | 595 | - fix enpower grid state error 596 | - added encharge grid state sensor 597 | - added solar grid state sensor 598 | - bump dependencies 599 | - cleanup 600 | 601 | ## [9.7.6] - (18.02.2025) 602 | 603 | ## Changes 604 | 605 | - stability and improvements 606 | - chore(config): tweak wording, thanks @nstuyvesant 607 | - Updates to the read me (spelling, punctuation, clarification), thanks @nstuyvesant 608 | - bump dependencies 609 | - cleanup 610 | 611 | ## [9.7.5] - (15.02.2025) 612 | 613 | ## Changes 614 | 615 | - moved custom characteristics and services to seperate file 616 | - added new opt_cheduless properties to storage setting 617 | - stability and improvements 618 | - cleanup 619 | 620 | ## [9.7.4] - (07.02.2025) 621 | 622 | ## Changes 623 | 624 | - stability and improvements 625 | 626 | ## [9.7.3] - (04.02.2025) 627 | 628 | ## Changes 629 | 630 | - update RESTFul 631 | 632 | ## [9.7.0] - (16.01.2025) 633 | 634 | ## Changes 635 | 636 | - added possibility to disable/enable log success, info, warn, error 637 | - config schema updated 638 | - redme updated 639 | - cleanup 640 | 641 | ## [9.6.12] - (03.01.2025) 642 | 643 | ## Changes 644 | 645 | - limit microinverters count to 70 due [#175](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/175) 646 | - fix powerLevel characteristics warning 647 | - fix display only active phase in live data 648 | 649 | ## [9.6.10] - (18.12.2024) 650 | 651 | ## Changes 652 | 653 | - update encharges led status 654 | - fix apparent power in live data 655 | - cleanup 656 | 657 | ## [9.6.9] - (17.12.2024) 658 | 659 | ## Changes 660 | 661 | - fix livedData characteristics warning [#173](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/173) 662 | - cleanup 663 | 664 | ## [9.6.8] - (16.12.2024) 665 | 666 | ## Changes 667 | 668 | - increase data refresh time issue [#172](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/172) 669 | - bump dependencies 670 | - cleanup 671 | 672 | ## [9.6.6] - (06.12.2024) 673 | 674 | ## Changes 675 | 676 | - better handle of error and cookies 677 | - bump dependencies 678 | - config.schema updated 679 | - cleanup 680 | 681 | ## [9.6.5] - (03.12.2024) 682 | 683 | ## Changes 684 | 685 | - check JWT toke is installer or user 686 | - add JWT Token installer option if use own generated token 687 | - config.schema updated 688 | - redme updated 689 | - cleanup 690 | 691 | ## [9.6.4] - (02.12.2024) 692 | 693 | ## Changes 694 | 695 | - prevent crasch if PLC Level is enabled and credentials data is not installer 696 | 697 | ## [9.6.3] - (02.12.2024) 698 | 699 | ## Changes 700 | 701 | - prevent crasch if production control is enabled and credentials data is not installer 702 | 703 | ## [9.6.0] - (30.11.2024) 704 | 705 | ## Changes 706 | 707 | - move from commonJS to esm module 708 | - moved constants.json to constants.js 709 | - cleanup 710 | 711 | ## [9.5.3] - (28.11.2024) 712 | 713 | ## Changes 714 | 715 | - better handle cookie and own token 716 | - config schema updated 717 | - cleanup 718 | 719 | ## [9.5.2] - (28.11.2024) 720 | 721 | ## Changes 722 | 723 | - fix display duplicate credentials in UI 724 | - better handle cookie and token 725 | - bump dependencies 726 | - config schema updated 727 | - cleanup 728 | 729 | ## [9.5.1] - (20.11.2024) 730 | 731 | ## Changes 732 | 733 | - fix reference error before initialization 734 | 735 | ## [9.5.0] - (19.11.2024) 736 | 737 | ## Changes 738 | 739 | - added possibility to select compare mode for power and energy level sensors 740 | - config schema updated 741 | - readme updated 742 | - cleanup 743 | 744 | ## [9.4.4] - (18.11.2024) 745 | 746 | ## Changes 747 | 748 | - fix data refresh after error occured 749 | - fix validate own token 750 | 751 | ## [9.4.3] - (17.11.2024) 752 | 753 | ## Changes 754 | 755 | - fix [#163](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/163) 756 | - added node 23 support 757 | - jwt token get and check refactor 758 | - correct some logs wording 759 | - cleanup 760 | 761 | ## [9.4.2] - (11.11.2024) 762 | 763 | ## Changes 764 | 765 | - fix reconnect if error ocurred during start 766 | - correct some logs wording 767 | - config.schema updated 768 | - cleanup 769 | 770 | ## [9.4.1] - (30.10.2024) 771 | 772 | ## Changes 773 | 774 | - fix stop data updating after error occured [#161](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/161) 775 | - added config schema validation 776 | - update dependencies 777 | - config.schema updated 778 | - cleanup 779 | 780 | ## [9.4.0] - (17.09.2024) 781 | 782 | ## Changes 783 | 784 | - added encharge profile sensors 785 | - fix battery/encharge state and backup level delay 786 | - fix grid state sensor 787 | - move some message to warn 788 | - use async/await for impulse generator 789 | - update dependencies 790 | - cleanup 791 | 792 | ## [9.3.5] - (31.08.2024) 793 | 794 | ## Changes 795 | 796 | - required upcomming homebridge 2.x.x required 797 | - fix [#153](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/153) 798 | - error handle improvements 799 | - increase axios timeout to 25sec 800 | - cleanup 801 | 802 | ## [9.3.4] - (27.08.2024) 803 | 804 | ## Changes 805 | 806 | - fix restFul data sampling response 807 | - fix duplicate start run afer error occur 808 | - fix characteristic Rest Power warning 809 | - increase axios timeout to 20sec 810 | - cleanup 811 | 812 | ## [9.3.3] - (23.08.2024) 813 | 814 | ## Changes 815 | 816 | - fix [#151](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/151) 817 | 818 | ## [9.3.0] - (23.08.2024) 819 | 820 | ## Changes 821 | 822 | - add control over RESTFul POST JSON Object 823 | - fix RESRFul enable 824 | - add timeout to axios 825 | - return axios error message instead of object if exist 826 | 827 | ## [9.2.9] - (21.08.2024) 828 | 829 | ## Changes 830 | 831 | - fix energy level sensors 832 | - refactor backbone app code to get envoy dev id 833 | - refactor envoy password calculate code 834 | - refactor installer password calculate code 835 | - add some warn message and allow app working without some not mandatory data 836 | 837 | ## [9.2.8] - (20.08.2024) 838 | 839 | ## Changes 840 | 841 | - fix encharge live data display 842 | - fix data refresh control 843 | - fix backup level sensors 844 | - cleanup 845 | 846 | ## [9.2.6] - (19.08.2024) 847 | 848 | ## Changes 849 | 850 | - fix [#149](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/149) 851 | 852 | ## [9.2.5] - (19.08.2024) 853 | 854 | ## Changes 855 | 856 | - fix correct display error instead empty object 857 | - move some error to warn and prevent to reconnect to envoy 858 | 859 | ## [9.2.4] - (19.08.2024) 860 | 861 | ## Changes 862 | 863 | - fix [#150](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/150) 864 | - fix voltage divide 865 | - correct some error logs 866 | - cleanup 867 | 868 | ## [9.2.3] - (18.08.2024) 869 | 870 | ## Changes 871 | 872 | - use warn instead error for not required data 873 | - cleanup 874 | 875 | ## [9.2.2] - (18.08.2024) 876 | 877 | ## Changes 878 | 879 | - fix [#149](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/149) 880 | - loging refactor 881 | - corect catch error 882 | - cleanup 883 | 884 | ## [9.2.0] - (16.08.2024) 885 | 886 | ## Changes 887 | 888 | - add generator mode Off/On/Auto control from home app as a extra tiles 889 | - arf profile refactor 890 | - cleanup 891 | 892 | ## [9.1.3] - (16.08.2024) 893 | 894 | ## Changes 895 | 896 | - decrease homebridge requirements to 1.8.0 897 | 898 | ## [9.1.2] - (16.08.2024) 899 | 900 | ## Changes 901 | 902 | - dynamically display arf profile only if supported 903 | 904 | ## [9.1.1] - (16.08.2024) 905 | 906 | ## Changes 907 | 908 | - fix PLC Level warning [#148](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/148) 909 | 910 | ## [9.1.0] - (16.08.2024) 911 | 912 | ## Changes 913 | 914 | - added enchrge profile cintrol over mqtt 915 | - added enpower state control over mqtt 916 | - added generator mode control over mqtt 917 | - cleanup 918 | 919 | ## [9.0.2] - (14.08.2024) 920 | 921 | ## Changes 922 | 923 | - fix threw new error characteristics 924 | 925 | ## [9.0.1] - (14.08.2024) 926 | 927 | ## Changes 928 | 929 | - fix corect remove sensitive data from config mqtt 930 | - remove sensitive data from debug log 931 | - hide passwords, tokens, serial numbers, by typing and display in Config UI 932 | - remove return duplicate promises from whole code 933 | 934 | ## [9.0.0] - (14.08.2024) 935 | 936 | ## Changes 937 | 938 | ### After update to v9.0.0 RESTFull and MQTT config settings need to be updated 939 | 940 | - support for Homebridge v2.0.0 941 | - full code refactor 942 | - RESTFul and MQTT config refactor 943 | - renamed config properties, `supportProductionPowerMode` to `supportPowerProductionState` 944 | - renamed config properties, `powerProductionControl` to `powerProductionStateControl` 945 | 946 | - system data refresh 947 | - added native control from home app as a extra tile 948 | - added control direct from envoy section, 3rd party app 949 | - added state sensor 950 | 951 | - plc level refresh: 952 | - added native control from home app as a extra tile 953 | - power production: 954 | - added native control from home app as a extra tile 955 | - generator: 956 | - added state native control from home app as a extra tile 957 | - added state direct control from envoy section, 3rd party app 958 | - added state sensor 959 | - added mode sensors 960 | - enpower: 961 | - added grid state native control from home app as a extra tile 962 | - added grid state control direct from envoy section, 3rd party appp 963 | - added grid state sensor 964 | - added dry contacts native control from home app as a extra tile 965 | - added dry contacts state sensors 966 | - encharge: 967 | - added state sensor 968 | - added profile native control from home app as a extra tile 969 | - other changes 970 | - added possibility to enable accessory name as a prefix for all services 971 | - stability and performance improvements 972 | - dependencies updated 973 | - config schema updated 974 | - bug fixes 975 | - cleanup 976 | 977 | ## [8.1.1] - (04.08.2024) 978 | 979 | ## Changes 980 | 981 | - fix display and publish ensemble status and sensors 982 | 983 | ## [8.1.0] - (04.08.2024) 984 | 985 | ## Changes 986 | 987 | - added new ensemble/encharge/solar sensor profile, grid-tied and grid-forming 988 | - config schema updated 989 | - redme updated 990 | - cleanup 991 | 992 | ## [8.0.2] - (04.08.2024) 993 | 994 | ## Changes 995 | 996 | - fix [#142](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/142). 997 | - fix characteristic name for encharge profile 998 | - add missing optional characteristic for enphaseWirelessConnectionKitService 999 | - redme updated 1000 | - cleanup 1001 | 1002 | ## [8.0.0] - (07.07.2024) 1003 | 1004 | ## Changes 1005 | 1006 | ### After update to v8.0.0 and above from plevious version all sennsors need to be activated in plugin config again 1007 | 1008 | - added possibility to set indyvidual characteristic type for sensors, `0 - None/Disabled`, `1 - Motion Sensor`, `2 - Occupancy Sensor`, `3 - Contact Sensor`. 1009 | - config schema updated 1010 | - redme updated 1011 | - cleanup 1012 | 1013 | ## [7.16.0] - (23.06.2024) 1014 | 1015 | ## Changes 1016 | 1017 | - added possibility to use Your own generated Token [#140](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/140) 1018 | - config schema updated 1019 | - redme updated 1020 | - cleanup 1021 | 1022 | ## [7.15.4] - (18.06.2024) 1023 | 1024 | ## Changes 1025 | 1026 | - bump node modules ws [#139](https://github.com/grzegorz914/homebridge-enphase-envoy/pull/139) 1027 | 1028 | ## [7.15.3] - (18.06.2024) 1029 | 1030 | ## Changes 1031 | 1032 | - polling code refactor, added impulse generator 1033 | - remove production properties from Q-Relay accessory 1034 | - cleanup 1035 | 1036 | ## [7.15.2] - (09.06.2024) 1037 | 1038 | ## Changes 1039 | 1040 | - remove possibility to enable/disable support for live data and ensemble status, now is check automatically 1041 | - moved refresh ensemble status refres time to envoy section 1042 | - config schema updated 1043 | - cleanup 1044 | 1045 | ## [7.15.1] - (08.06.2024) 1046 | 1047 | ## Changes 1048 | 1049 | - added compare mode to the encharge backup level sensors 1050 | - config schema updated 1051 | 1052 | ## [7.15.0] - (08.06.2024) 1053 | 1054 | ## Changes 1055 | 1056 | - added encharge backup level sensors 1057 | - readme updated 1058 | - config schema updated 1059 | - cleanup 1060 | 1061 | ## [7.14.9] - (08.06.2024) 1062 | 1063 | ## Changes 1064 | 1065 | - refactor check JWT token 1066 | - refactor check arf profile 1067 | - correct some logs 1068 | - cleanup 1069 | 1070 | ## [7.14.8] - (01.06.2024) 1071 | 1072 | ## Changes 1073 | 1074 | - fix 401 error after envoy reboot and refresh cocies 1075 | - fix characteristics warning for arf profile 1076 | - increase time for check token expired 1077 | = bump dependencies 1078 | - cleanup 1079 | 1080 | ## [7.14.5] - (12.05.2024) 1081 | 1082 | ## Changes 1083 | 1084 | - refactor token check and request 1085 | - added infot about token time expired 1086 | - cleanup 1087 | 1088 | ## [7.14.4] - (06.05.2024) 1089 | 1090 | ## Changes 1091 | 1092 | - stop data polling if token expired, start after refreshed 1093 | - fixed power peak handle 1094 | - refactor code in passwords calculation and check jwt token 1095 | 1096 | ## [7.14.0] - (27.04.2024) 1097 | 1098 | ## Changes 1099 | 1100 | - added support to check and control Production Power Mode, firmware 7.x.x required installer credentials data 1101 | - added support to check PLC Level, firmware 7.x.x required installer credentials data 1102 | - added support to check and control Production Power Mode over MQTT protocol, firmware 7.x.x required installer credentials data 1103 | - added support to check PLC Level over MQTT protocol, firmware 7.x.x required installer credentials data 1104 | - config.schema updated 1105 | - cleanup 1106 | 1107 | ## [7.13.0] - (27.04.2024) 1108 | 1109 | ## Changes 1110 | 1111 | ### After update to v7.13.0 and above from plevious version the refresh time need to be configured again 1112 | 1113 | - changed data refresh time from (ms) go (sec) and precision 0.5 1114 | - prevent to set refresh time to 0, now minimum is 0.5 sec 1115 | - config.schema updated 1116 | - cleanup 1117 | 1118 | ## [7.11.14] - (26.02.2024) 1119 | 1120 | ## Changes 1121 | 1122 | - fix [#127](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/127) 1123 | - fix [#126](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/126) 1124 | - fix [#125](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/125) 1125 | - cleanup 1126 | 1127 | ## [7.11.0] - (11.02.2024) 1128 | 1129 | ## Changes 1130 | 1131 | ### After update to v7.11.0 and above from plevious version the grid mode sensors need to be configured again 1132 | 1133 | - added support to create multiple enpower/encharge/solar grid mode sensors and select grid mode to match 1134 | - config.schema updated 1135 | - cleanup 1136 | 1137 | ## [7.10.0] - (10.02.2024) 1138 | 1139 | ## Changes 1140 | 1141 | - added support for Envoy Firmware 8.x.x 1142 | - added support for storage CT meters 1143 | - fixed [#114](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/114) 1144 | - config.schema updated 1145 | - cleanup 1146 | 1147 | ## [7.9.0] - (01.01.2024) 1148 | 1149 | ## Changes 1150 | 1151 | - added [#118](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/118) 1152 | - added state and level lightbulb for ac bateries and encharges 1153 | - config.schema updated 1154 | - cleanup 1155 | 1156 | ## [7.8.0] - (23.12.2023) 1157 | 1158 | ## Changes 1159 | 1160 | ### After update to v7.8.0 and above from plevious version the sensors need to be configured again 1161 | 1162 | - added [#117](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/117) 1163 | - added possibility to set custom name for sensors 1164 | - added possibility to activate/deactivate sensors 1165 | - added possibility to create multiple sensors for power and energy level 1166 | - config.schema updated 1167 | - cleanup 1168 | 1169 | ## [7.7.5] - (05.12.2023) 1170 | 1171 | ## Changes 1172 | 1173 | - fix missing aasync/wait for microinverters data update 1174 | - refactor code in section data update 1175 | - fix characteristic warning [#115](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/115) 1176 | - better handle to fix [#112](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/112) 1177 | - config.schema updated 1178 | - cleanup 1179 | 1180 | ## [7.7.4] - (02.12.2023) 1181 | 1182 | ## Changes 1183 | 1184 | - fix [#112](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/112) 1185 | - cleanup 1186 | 1187 | ## [7.7.3] - (29.11.2023) 1188 | 1189 | ## Changes 1190 | 1191 | - fix [#112](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/112) 1192 | - cleanup 1193 | 1194 | ## [7.7.2] - (26.11.2023) 1195 | 1196 | ## Changes 1197 | 1198 | - added debug log for services prepare 1199 | - prepare for generators support 1200 | - cleanup 1201 | 1202 | ## [7.7.1] - (26.11.2023) 1203 | 1204 | ## Changes 1205 | 1206 | - dynamically add *Live Data* characteristics based on installed devices 1207 | - cleanup 1208 | 1209 | ## [7.7.0] - (26.11.2023) 1210 | 1211 | ## Changes 1212 | 1213 | - added *Live Data PV* cheracteristics to the HomeKit 1214 | - added *Live Data Storage* cheracteristics to the HomeKit 1215 | - added *Live Data Grid* cheracteristics to the HomeKit 1216 | - added *Live Data Load* cheracteristics to the HomeKit 1217 | - added *Live Data Generator* cheracteristics to the HomeKit 1218 | - fix [#85](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/85) 1219 | - config schema updated 1220 | - cleanup 1221 | 1222 | ## [7.5.0] - (20.10.2023) 1223 | 1224 | ## Changes 1225 | 1226 | ### After update to v7.5.0 and above from plevious version the sensors need to be configured again 1227 | 1228 | - added *Power State* contact sensor (Consumption Total) for automations and notifications in HomeKit 1229 | - added *Energy State* contact sensor (Consumption Total) for automations and notifications in HomeKit 1230 | - added *Energy Level* contact sensor (Consumption Total) for automations and notifications in HomeKit 1231 | - added *Power State* contact sensor (Consumption Net) for automations and notifications in HomeKit 1232 | - added *Energy State* contact sensor (Consumption Net) for automations and notifications in HomeKit 1233 | - added *Energy Level* contact sensor (Consumption Net) for automations and notifications in HomeKit 1234 | - added *Enpower Grid State* contact sensor for automations and notifications in HomeKit 1235 | - added *Encharge Grid State* contact sensor for automations and notifications in HomeKit 1236 | - added *Solar Grid State* contact sensor for automations and notifications in HomeKit 1237 | - bump node to min 18.x.x and homebridge to 1.6 1238 | - config schema updated 1239 | - redme update 1240 | - cleanup 1241 | 1242 | ## [7.4.0] - (25.07.2023) 1243 | 1244 | ## Changes 1245 | 1246 | - added *Energy State* contact sensor for production monitoring, which can be used for notification and automations in HomeKit. 1247 | - added *Energy Level* contact sensor for production monitoring, which can be used for notification and automations in HomeKit. 1248 | - config schema updated 1249 | - cleanup 1250 | 1251 | ## [7.3.0] - (20.07.2023) 1252 | 1253 | ## Changes 1254 | 1255 | - added *Power Production On/Off* contact sensor for production monitoring, which can be used for notification and automations in HomeKit. 1256 | - Use encodeURIComponent in EnvoyToken URLs - thanks @chrisjshull 1257 | - config schema updated 1258 | - cleanup 1259 | 1260 | ## [7.2.0] - (17.07.2023) 1261 | 1262 | ## Changes 1263 | 1264 | - added power production level (0-100%) displayed as brightness level in Home app based on all microinvertzers power configured in plugin config 1265 | - config schema updated 1266 | 1267 | ## [7.1.0] - (16.07.2023) 1268 | 1269 | ## Changes 1270 | 1271 | - added accessory switch to display in Home app curren state of power production, if Production Power > 0 then switch is ON 1272 | - config schema updated 1273 | 1274 | ## [7.0.0] - (14.07.2023) 1275 | 1276 | ## After Update to this version need to make corespondent changes in plugin config 1277 | 1278 | ## Changes 1279 | 1280 | - added support to get JWT Token automatically from enlighten server using user credentials data 1281 | - added support to check expired JWT Token and get new if expired 1282 | - added debug for RESTFul server 1283 | - added `token` to the RESTFul server request 1284 | - added `Token` to the MQTT publisher 1285 | - config schema updated 1286 | - cleanup 1287 | 1288 | ### Removed properties 1289 | 1290 | - `envoyFirmware7xxToken` 1291 | 1292 | ### Added properties 1293 | 1294 | - `enlightenUser` 1295 | - `enlightenPasswd` 1296 | - `envoySerialNumber` 1297 | 1298 | ## [6.7.0] - (27.02.2023) 1299 | 1300 | ## Changes 1301 | 1302 | - added powerful RESTFul server to use with own automations 1303 | - cleanup 1304 | - config.schema updated 1305 | 1306 | ## [6.6.0] - (26.02.2023) 1307 | 1308 | ## Changes 1309 | 1310 | - added for ensemble summary Rest Power 1311 | - added for ensemble summary AGG Max Energy 1312 | - added for ensemble summary Encharges AGG SoC 1313 | - added for ensemble summary Encharges AGG Rated Power 1314 | - added for ensemble summary bias frequency, voltage for phasa L2/B and L3/C 1315 | - prevent HB crash if for some reason prepare accessory fail 1316 | - properties updated/added 1317 | - bump dependencies 1318 | - cleanup 1319 | 1320 | ## [6.5.0] - (17.01.2023) 1321 | 1322 | ## Changes 1323 | 1324 | - added possibility to set refresh time for live dta, meters data and production ct 1325 | 1326 | ## [6.4.1] - (16.01.2023) 1327 | 1328 | ## Changes 1329 | 1330 | - fix wirreles konnections kit crash 1331 | 1332 | ## [6.4.0] - (15.01.2023) 1333 | 1334 | ## Changes 1335 | 1336 | - code cleanup 1337 | - config schema updated 1338 | - stability improvements 1339 | - reduce memory and cpu ussage 1340 | - added *Power Peak* contact sensors for production, consumption total/net which can be used for notification and automations in HomeKit. 1341 | - fix display wirelesskit characteristics hovewer is not instlled 1342 | - fix [#73](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/73) 1343 | 1344 | ## [6.3.2] - (14.01.2023) 1345 | 1346 | ## Changes 1347 | 1348 | - fix [#71](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/71) 1349 | - fix [#72](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/72) 1350 | - fix read grid profile name 1351 | - added new properties to ensemble status data 1352 | - added profile data to mqtt 1353 | 1354 | ## [6.3.1] - (12.01.2023) 1355 | 1356 | ## Changes 1357 | 1358 | - code cleanup 1359 | - stability and performance improvement 1360 | 1361 | ## [6.3.0] - (10.01.2023) 1362 | 1363 | ## Changes 1364 | 1365 | - added possibility enable/disable support to check *Laive Data* 1366 | - Envoy cpu load reduction 1367 | - code cleanup 1368 | - performance improvement 1369 | 1370 | ## [6.2.0] - (10.01.2023) 1371 | 1372 | ## Changes 1373 | 1374 | - added possibility enable/disable support to check *Ensemble Status* 1375 | - code cleanup/refactor 1376 | - config schema updated 1377 | 1378 | ## [6.1.0] - (09.01.2023) 1379 | 1380 | ## Changes 1381 | 1382 | - fix [#70](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/70) 1383 | - added possibility enable/disable support to check *PLC Level* 1384 | - added possibility enable/disable support to check/control production *Power Mode* 1385 | - code cleanup 1386 | 1387 | ## [6.0.9] - (09.01.2023) 1388 | 1389 | ## Changes 1390 | 1391 | - fix [#69](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/69) 1392 | - added missing promise 1393 | - code cleanup 1394 | - some log corrections 1395 | 1396 | ## [6.0.8] - (05.01.2023) 1397 | 1398 | ## Changes 1399 | 1400 | - code cleanup 1401 | - log units and text corrections 1402 | - added auto check plc communication level on startup 1403 | - added encharges plc level characteristic 1404 | 1405 | ## [6.0.7] - (30.12.2022) 1406 | 1407 | ## Changes 1408 | 1409 | - fixed wireless connection kit set to true 1410 | 1411 | ## [6.0.6] - (30.12.2022) 1412 | 1413 | ## Changes 1414 | 1415 | - fixed wireless connection kit characteristics 1416 | 1417 | ## [6.0.5] - (29.12.2022) 1418 | 1419 | ## Changes 1420 | 1421 | - fixed ensembles, encharges and enpowers read data [#66](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/66) 1422 | - publish live data to MQTT if Envoy firmware >= 7.x.x 1423 | - bump dependencies 1424 | 1425 | ## [6.0.4] - (14.12.2022) 1426 | 1427 | ## Changes 1428 | 1429 | - code optimize 1430 | 1431 | ## [6.0.3] - (14.12.2022) 1432 | 1433 | ## Changes 1434 | 1435 | - fix axios instance with token 1436 | 1437 | ## [6.0.2] - (14.12.2022) 1438 | 1439 | ## Changes 1440 | 1441 | - digestAuth code refactor 1442 | - code cleanup 1443 | 1444 | ## [6.0.1] - (13.12.2022) 1445 | 1446 | ## Changes 1447 | 1448 | - fixed JWT authorization proces and store cookies for data request 1449 | - code optimization 1450 | - big thanks @NoSnow3 and @BenouGui for test 1451 | 1452 | ## [6.0.0] - (11.12.2022) 1453 | 1454 | ## Changes 1455 | 1456 | - added support for Envoy with firmware 7.x.x and Token Authorization 1457 | - config schema updated 1458 | - big thanks @NoSnow3 for test 1459 | 1460 | ## [5.9.7] - (06.12.2022) 1461 | 1462 | ## Changes 1463 | 1464 | - bump dependencies 1465 | 1466 | ## [5.9.6] - (15.09.2022) 1467 | 1468 | ## Changes 1469 | 1470 | - fix refresh inventory data 1471 | - bump dependencies 1472 | 1473 | ## [5.9.4] - (10.09.2022) 1474 | 1475 | ## Changes 1476 | 1477 | - cleanup 1478 | - fix mqtt 1479 | - bump dependencies 1480 | 1481 | ## [5.9.3] - (29.08.2022) 1482 | 1483 | ## Changes 1484 | 1485 | - cleanup 1486 | - update mqtt topics 1487 | 1488 | ## [5.9.2] - (26.08.2022) 1489 | 1490 | ## Changes 1491 | 1492 | - cleanup 1493 | 1494 | ## [5.9.1] - (26.08.2022) 1495 | 1496 | ## Changes 1497 | 1498 | - convert password generator to iuse promises async/await 1499 | - cleanup 1500 | 1501 | ## [5.9.0] - (25.08.2022) 1502 | 1503 | ## Changes 1504 | 1505 | - added installer password generator, no need generate it manually in external generator 1506 | - config schema updated 1507 | 1508 | ## [5.8.4] - (25.08.2022) 1509 | 1510 | ## Changes 1511 | 1512 | - rebuild refresh data process 1513 | - config schema updated 1514 | - cosmetics changes 1515 | 1516 | ## [5.8.3] - (23.08.2022) 1517 | 1518 | ## Changes 1519 | 1520 | - fix [#55](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/55) 1521 | 1522 | ## [5.8.2] - (21.08.2022) 1523 | 1524 | ## Changes 1525 | 1526 | - code cleanup 1527 | - better fix Power characteristic warning negative value [#54](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/54) 1528 | 1529 | ## [5.8.1] - (13.08.2022) 1530 | 1531 | ## Changes 1532 | 1533 | - fix Power characteristic warning negative value [#54](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/54) 1534 | 1535 | ## [5.8.0] - (12.08.2022) 1536 | 1537 | ## Changes 1538 | 1539 | - added possibility automatically 'Power peak reset' every day, week, month 1540 | - config schema updated 1541 | 1542 | ## [5.7.8] - (08.08.2022) 1543 | 1544 | ## Changes 1545 | 1546 | - fix [#53](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/53) 1547 | 1548 | ## [5.7.7] - (08.08.2022) 1549 | 1550 | ## Changes 1551 | 1552 | - fix production *Power peak detected* state 1553 | - rebuild log 1554 | 1555 | ## [5.7.6] - (07.08.2022) 1556 | 1557 | ## Changes 1558 | 1559 | - fix auto/manual consumptions 'Power peak reset and save' 1560 | - log updated 1561 | - properties in code updated 1562 | 1563 | ## [5.7.3] - (07.08.2022) 1564 | 1565 | ## Changes 1566 | 1567 | - fix auto 'Power peak reset' at midnight 1568 | 1569 | ## [5.7.2] - (06.08.2022) 1570 | 1571 | ## Changes 1572 | 1573 | - fix characteristic 'Power peak reset' warning 1574 | 1575 | ## [5.7.1] - (06.08.2022) 1576 | 1577 | ## Changes 1578 | 1579 | - fix update button state characteristics for power peak reset 1580 | 1581 | ## [5.7.0] - (06.08.2022) 1582 | 1583 | ## Changes 1584 | 1585 | - added possibility to manuall reset *Power peak* (in accessory using button) 1586 | - added possibility to automatically reset *Power peak* at midnight (in plugin setting configurable) 1587 | - updated config schema 1588 | 1589 | ## [5.6.22] - (06.08.2022) 1590 | 1591 | ## Changes 1592 | 1593 | - rename *Power Max* to *Power Peak* 1594 | - added extra refresh data for production (microinverters) 1595 | 1596 | ## [5.6.21] - (03.08.2022) 1597 | 1598 | ## Changes 1599 | 1600 | - fix [#52](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/52) 1601 | 1602 | ## [5.6.20] - (03.08.2022) 1603 | 1604 | ## Changes 1605 | 1606 | - added possibility to disable display device info in log after plugin restart 1607 | - check required properties to create accessory 1608 | - correct some logs typos 1609 | 1610 | ## [5.6.15] - (02.08.2022) 1611 | 1612 | ## Changes 1613 | 1614 | - fix refresh power and energy production data if no meters are installed 1615 | 1616 | ## [5.6.14] - (02.08.2022) 1617 | 1618 | ## Changes 1619 | 1620 | - fix display undefinded Power and Energy type if no meters are installed 1621 | 1622 | ## [5.6.13] - (23.07.2022) 1623 | 1624 | ## Changes 1625 | 1626 | - refactor information service 1627 | 1628 | ## [5.6.12] - (11.05.2022) 1629 | 1630 | ## Changes 1631 | 1632 | - fix [#50](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/50) 1633 | 1634 | ## [5.6.9] - (25.04.2022) 1635 | 1636 | ## Changes 1637 | 1638 | - update dependencies 1639 | 1640 | ## [5.6.8] - (25.04.2022) 1641 | 1642 | ## Changes 1643 | 1644 | - refactor send mqtt message 1645 | 1646 | ## [5.6.7] - (24.04.2022) 1647 | 1648 | ## Changes 1649 | 1650 | - update config.schema.json 1651 | 1652 | ## [5.6.6] - (30.03.2022) 1653 | 1654 | ## Changes 1655 | 1656 | - prevent poll Meters Reading Data if no Meters are installed 1657 | - prevent poll Microinverters Power Data if envoy password is not set 1658 | 1659 | ## [5.6.5] - (30.03.2022) 1660 | 1661 | ## Changes 1662 | 1663 | - refresh time for Meters Reading Data to 1,5sec and Production CT Data to 3 sec. 1664 | 1665 | ## [5.6.4] - (29.03.2022) 1666 | 1667 | ## Changes 1668 | 1669 | - fixed read microinverters data (error 401) if envoy uses standard password, fix [#48](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/48) 1670 | 1671 | ## [5.6.3] - (29.03.2022) 1672 | 1673 | ## Added 1674 | 1675 | - debug mode for MQTT Client 1676 | - 1677 | 1678 | ## Changes 1679 | 1680 | - update check state data 1681 | - update debug logging 1682 | - removed refresh interval 1683 | - update config schema 1684 | - removed Entrez Authorization functionality for Envoy with firmware 7.x.x at this time 1685 | 1686 | ## [5.6.1] - (20.02.2022) 1687 | 1688 | ## Added 1689 | 1690 | - wrire envoy device id to file 1691 | 1692 | ## [5.6.0] - (19.02.2022) 1693 | 1694 | ## Added 1695 | 1696 | - Entrez Authorization for Envoy with firmware 7.x.x (test phase) 1697 | 1698 | ## [5.5.0] - (17.02.2022) 1699 | 1700 | ## Added 1701 | 1702 | - MQTT Client, publish all PV installation data 1703 | - Debug mode 1704 | - Prepare for entrez authorization 1705 | 1706 | ## Changes 1707 | 1708 | - update dependencies 1709 | - code refactor 1710 | 1711 | ## [5.4.34] - (18.01.2022) 1712 | 1713 | ## Changes 1714 | 1715 | - update dependencies 1716 | 1717 | ## [5.4.33] - (17.01.2022) 1718 | 1719 | ## Changes 1720 | 1721 | - update dependencies 1722 | 1723 | ## [5.4.32] - (29.12.2021) 1724 | 1725 | - prepare directory and files synchronously 1726 | 1727 | ## [5.4.30] - (28.12.2021) 1728 | 1729 | - update node minimum requirements 1730 | 1731 | ## [5.4.29] - (20.11.2021) 1732 | 1733 | ## Changes 1734 | 1735 | - cosmetics 1736 | 1737 | ## [5.4.21] - (25.09.2021) 1738 | 1739 | ## Changes 1740 | 1741 | - code cleanup 1742 | 1743 | ## [5.4.19] - (24.09.2021) 1744 | 1745 | ## Changes 1746 | 1747 | ### WARNING - after this update nedd to remove and add accessory to the HomeKit again 1748 | 1749 | - code cleanup 1750 | - stability improvements 1751 | 1752 | ## [5.4.18] - (24.09.2021) 1753 | 1754 | ## Changes 1755 | 1756 | - code cleanup 1757 | - fix wrong voltage display, 1-phase instalation 1758 | 1759 | ## [5.4.17] - (19.09.2021) 1760 | 1761 | ## Changes 1762 | 1763 | - code cleanup 1764 | 1765 | ## [5.4.15] - (09.09.2021) 1766 | 1767 | ## Changes 1768 | 1769 | - bump dependencies 1770 | - stability improvements 1771 | - performance improvements 1772 | 1773 | ## [5.4.14] - (05.09.2021) 1774 | 1775 | ## Changes 1776 | 1777 | - bump dependencies 1778 | 1779 | ## [5.4.13] - (04.09.2021) 1780 | 1781 | ## Changes 1782 | 1783 | - bump dependencies 1784 | 1785 | ## [5.4.1] - (22.08.2021) 1786 | 1787 | ## Changes 1788 | 1789 | - removed *envoyDevId* property, now is detect automatically 1790 | 1791 | ## [5.4.0] - (21.08.2021) 1792 | 1793 | ## Changes 1794 | 1795 | - removed urllib 1796 | - added digestAuth method to Axios 1797 | - code rebuild and cleanup 1798 | - some fixes and improvements 1799 | 1800 | ## [5.3.1] - (21.08.2021) 1801 | 1802 | ## Changes 1803 | 1804 | - charcterristics data format fixes 1805 | - added grid profile characteristic for ensemble 1806 | - code rebuild and cleanup 1807 | 1808 | ## [5.3.0] - (17.08.2021) 1809 | 1810 | ## Changes 1811 | 1812 | - added wireless connection kit characteristics 1813 | - code rebuild and cleanup 1814 | 1815 | ## [5.2.15] - (16.08.2021) 1816 | 1817 | ## Changes 1818 | 1819 | - finally fixed not reconized ensemble (enpower and encharges) devices in previous versions 1820 | 1821 | ## [5.2.0] - (15.08.2021) 1822 | 1823 | ## Changes 1824 | 1825 | - added possibility Enable/Disable Power Production (in envoy section) 1826 | 1827 | ## [5.1.0] - (13.08.2021) 1828 | 1829 | ## Changes 1830 | 1831 | - added system Power Production state(in envoy section) 1832 | - added enpower status service 1833 | - fixed not reconized ensemble (enpower and encharges) devices in previous versions 1834 | - updated SKU and Part Nr. 1835 | - code rebuild and cleanup 1836 | - other fixes and improvements 1837 | 1838 | ## [5.0.0] - (05.08.2021) 1839 | 1840 | ## Changes 1841 | 1842 | - removed deprecated inherits and moved all characterictics to use ES6 class 1843 | 1844 | ## [4.9.0] - (03.08.2021) 1845 | 1846 | ## Changes 1847 | 1848 | - added support for Ensemble (Enpowers and Encharges) 1849 | - fixed wrong named Encharges to AC Batteries 1850 | - other fixes and performance improvements 1851 | 1852 | ## [4.8.0] - (12.03.2021) 1853 | 1854 | ## Changes 1855 | 1856 | - added possibility to check communications level of all devces on user request 1857 | - fixed many small bugs 1858 | - code cleanup 1859 | 1860 | ## [4.7.0] - (04.03.2021) 1861 | 1862 | ## Changes 1863 | 1864 | - update config.chema 1865 | - fixed many small bugs 1866 | - correct identyfi all hardware 1867 | - code cleanup 1868 | 1869 | ## [4.6.0] - (24.02.2021) 1870 | 1871 | ## Changes 1872 | 1873 | - added Characteristics for Apparent and Reactive Power 1874 | - fixed some bugs 1875 | 1876 | ## Important note v4.5.0 and above 1877 | 1878 | Version 4.5.0 and above need to be used with Homebridge min. v1.3.0. 1879 | 1880 | ## [4.5.0] - (23.02.2021) 1881 | 1882 | ## Changes 1883 | 1884 | - code rebuild, use Characteristic.onSet/onGet 1885 | - require Homebridge 1.3.x or above 1886 | 1887 | ## [4.4.0] - (10.02.2021) 1888 | 1889 | ## Changs 1890 | 1891 | - restored possibility to set own user and password for envoy 1892 | - added characteristic for communication level Q-Relays, Encharges, Microinverters 1893 | - added characteristic for all data from Encharges 1894 | - other improvements and fixes 1895 | 1896 | ## [4.3.0] - (07.02.2021) 1897 | 1898 | ## Changs 1899 | 1900 | - added more characteristics for encharges 1901 | - added characteristics for Current, Voltage and Power Factor 1902 | - fixed reported bugs 1903 | 1904 | ## [4.2.0] - (03.02.2021) 1905 | 1906 | ## Changs 1907 | 1908 | - added evnoy characteristics 1909 | - fixes and corrections 1910 | 1911 | ## [4.1.0] - (02.02.2021) 1912 | 1913 | ## Changs 1914 | 1915 | - removed envoyUser, envoyPasswd, Firmware and SerialNumber, now detect the data automatically 1916 | - data refresh improvements 1917 | - reconfigured config schema 1918 | - other fixes and corrections 1919 | 1920 | ## Important note v4.0.0 and above 1921 | 1922 | Version 4.0.0 whole new concept. 1923 | 1924 | ## [4.0.0] - (30.01.2021) 1925 | 1926 | ## Changs 1927 | 1928 | - refactoring whole code 1929 | - added Characteristics for Q-Relay, Meters, Microinverters, Encharges 1930 | - added whole base of status code all displayes in EVE or Controller app 1931 | - added and present state and power of all devices (Envoy, Q-Relay, Meters, Microinverters, Encharges) 1932 | - code cleanup and many more 1933 | 1934 | ## [3.6.0] - (29.01.2021) 1935 | 1936 | ## Changs 1937 | 1938 | - read Laast and Max Power of indyvidual inverters 1939 | - code rebuild 1940 | 1941 | ## [3.5.15] - (29.01.2021) 1942 | 1943 | ## Changs 1944 | 1945 | - list all devices in log with its status 1946 | 1947 | ## Important note v3.5.0 and above 1948 | 1949 | Version 3.5.0 detect automatically all installed devices, please check Your config after update to this version. 1950 | 1951 | ## [3.5.0] - (29.01.2021) 1952 | 1953 | ## Changs 1954 | 1955 | - full automatic check installed devices, Envoy, Inverters, Q-Relay, Meters, Encharges 1956 | - rebuild config 1957 | 1958 | ## [3.4.3] - (29.01.2021) 1959 | 1960 | ## Changs 1961 | 1962 | - added check for installed Q-Relay 1963 | - added check for installed Encharge 1964 | - added check for installed Meters 1965 | - reconfigured config menu 1966 | - code rebuild 1967 | 1968 | ## [3.3.15] - (26.01.2021) 1969 | 1970 | ## Changs 1971 | 1972 | - power Net and Total Max fixes 1973 | 1974 | ## [3.3.9] - (01.01.2021) 1975 | 1976 | ## Changs 1977 | 1978 | - bump dependiencies 1979 | 1980 | ## [3.3.5] - (22.10.2020) 1981 | 1982 | ## Changs 1983 | 1984 | - added encharge storage energy offset 1985 | - added possibility to select consumtion meter CT - Load only/Load with Solar production 1986 | - update config.schema 1987 | 1988 | ## [3.2.0] - (08.09.2020) 1989 | 1990 | ## Changs 1991 | 1992 | - added async/await function to read deviceInfo and updateStatus 1993 | 1994 | ## [3.1.0] - (06.09.2020) 1995 | 1996 | ## Changs 1997 | 1998 | - completly reconfigured config schema 1999 | 2000 | ## [3.0.15] - (05.09.2020) 2001 | 2002 | ## Changs 2003 | 2004 | - changed Characteristic.StatusActive to custom Characteristic.PowerMaxDetected 2005 | 2006 | ## [3.0.8] - (05.09.2020) 2007 | 2008 | ## Fix 2009 | 2010 | - fix wrong display power detection state 2011 | 2012 | ## [3.0.7] - (04.09.2020) 2013 | 2014 | ## Added 2015 | 2016 | - added Characteristic.StatusActive to identify Max Power Detection 2017 | 2018 | ## [3.0.4] - (04.09.2020) 2019 | 2020 | ## Fix 2021 | 2022 | - fix no display Last Seven Days energy 2023 | 2024 | ## [3.0.3] - (04.09.2020) 2025 | 2026 | ## Changes 2027 | 2028 | - code cleanup 2029 | 2030 | ## Important note 2031 | 2032 | Ab verion v3.0.0 accesory moved to Power Meter custom Characteristic, due to Apple HomeKit limitations right now only in EVE app displayed correctly, in HomeKit displayed as 'Unsupported'. If U want to use old CO2 sensor style just still with 2.x.x version 2033 | 2034 | ## [3.0.0] - (02.09.2020) 2035 | 2036 | ### New 2037 | 2038 | - accesory moved to Power Meter, due to Apple HomeKit limitations right now only in EVE app displayed, in HomeKit displayed as 'Unsupported'. 2039 | - added possibility to set lifetime energy offset for production, and consumption. 2040 | - added support for encharge storage. 2041 | 2042 | ## [2.3.0] - (28.08.2020) 2043 | 2044 | ### Added 2045 | 2046 | - added energy production and consumption tile (Today, Last 7D, Lifetime). 2047 | 2048 | ## [2.2.0] - (27.08.2020) 2049 | 2050 | ### Added 2051 | 2052 | - added possibility to display minus values, exported power to grid. 2053 | 2054 | ## [2.1.3] - (27.08.2020) 2055 | 2056 | ### Added 2057 | 2058 | - added extra accessory to present Total or Total and Net Consumption. Selectable in consumption power meter option. 2059 | 2060 | ## [2.0.6] - (27.08.2020) 2061 | 2062 | ### Added 2063 | 2064 | - added extra accessory to present Total Power Consumption if consumption Power meter is selected 2065 | 2066 | ## [1.1.2] - (25.08.2020) 2067 | 2068 | ### Changes 2069 | 2070 | - performance improvements 2071 | - other small fixes 2072 | 2073 | ## [1.1.0] - (09.08.2020) 2074 | 2075 | ### Added 2076 | 2077 | - performance improvements 2078 | 2079 | ## [1.0.3] - (02.07.2020) 2080 | 2081 | ### Fixed 2082 | 2083 | - fixed #2 crash if no production meters are installed 2084 | 2085 | ## [1.0.1] - (29.06.2020) 2086 | 2087 | ### Fixed 2088 | 2089 | - fixed display energy and power values 2090 | 2091 | ## [1.0.0] - (28.06.2020) 2092 | 2093 | ### Added 2094 | 2095 | - added possibility select consumption power meter 2096 | 2097 | ## [0.4.6] - (27.06.2020) 2098 | 2099 | ### Fixed 2100 | 2101 | - fixed display energy symbol in the log 2102 | 2103 | ## [0.4.5] - (27.06.2020) 2104 | 2105 | ### Added 2106 | 2107 | - added in the log possibility read all power and energy value 2108 | 2109 | ## [0.3.5] - (17.06.2020) 2110 | 2111 | ### Fixed 2112 | 2113 | - corrections in config.schema.json 2114 | 2115 | ## [0.3.0] - (15.06.2020) 2116 | 2117 | ### Added 2118 | 2119 | - added possibility to select production meter 2120 | 2121 | ## [0.2.0] - (010.06.2020) 2122 | 2123 | ### Added 2124 | 2125 | - stored max. Power Production too the file 2126 | - config.host now use 'envoy.local' path or Your configured iP adress 2127 | 2128 | ## [0.1.1] - (08.06.2020) 2129 | 2130 | ### Fixed 2131 | 2132 | - many fixes and more info in log 2133 | 2134 | ## [0.0.30] - (05.06.2020) 2135 | 2136 | - working release 2137 | 2138 | ## [0.0.1] - (05.06.2020) 2139 | 2140 | - initial release 2141 | --------------------------------------------------------------------------------