-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Migrate configuration format to allow multiple meters
- Loading branch information
Showing
10 changed files
with
248 additions
and
115 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
v18.15.0 | ||
v20.11.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,69 @@ | ||
#!/usr/bin/with-contenv bashio | ||
|
||
CONFIG=$(bashio::addon.options) | ||
|
||
# === Migrate 1.2.0 config === | ||
|
||
consumption_prm=$(echo "$CONFIG" | jq -r '."consumption PRM" // empty') | ||
if [ ! -z "$consumption_prm" ]; then | ||
bashio::addon.option 'meters[0].prm' "$consumption_prm" | ||
echo -e "\e[33mMoved consumption PRM to meters configuration\e[0m" | ||
fi | ||
|
||
consumption_token=$(echo "$CONFIG" | jq -r '."consumption token" // empty') | ||
if [ ! -z "$consumption_token" ]; then | ||
bashio::addon.option 'meters[0].token' "$consumption_token" | ||
echo -e "\e[33mMoved consumption token to meters configuration\e[0m" | ||
fi | ||
|
||
consumption_name=$(echo "$CONFIG" | jq -r '."consumption name" // empty') | ||
if [ ! -z "$consumption_name" ]; then | ||
bashio::addon.option 'meters[0].name' "$consumption_name" | ||
echo -e "\e[33mMoved consumption name to meters configuration\e[0m" | ||
fi | ||
|
||
consumption_action=$(echo "$CONFIG" | jq -r '."consumption action" // empty') | ||
if [ ! -z "$consumption_action" ]; then | ||
bashio::addon.option 'meters[0].action' "$consumption_action" | ||
echo -e "\e[33mMoved consumption action to meters configuration\e[0m" | ||
fi | ||
|
||
production_prm=$(echo "$CONFIG" | jq -r '."production PRM" // empty') | ||
if [ ! -z "$production_prm" ]; then | ||
bashio::addon.option 'meters[1].prm' "$production_prm" | ||
echo -e "\e[33mMoved production PRM to meters configuration\e[0m" | ||
fi | ||
|
||
production_token=$(echo "$CONFIG" | jq -r '."production token" // empty') | ||
if [ ! -z "$production_token" ]; then | ||
bashio::addon.option 'meters[1].token' "$production_token" | ||
echo -e "\e[33mMoved production token to meters configuration\e[0m" | ||
fi | ||
|
||
production_name=$(echo "$CONFIG" | jq -r '."production name" // empty') | ||
if [ ! -z "$production_name" ]; then | ||
bashio::addon.option 'meters[1].name' "$production_name" | ||
echo -e "\e[33mMoved production name to meters configuration\e[0m" | ||
fi | ||
|
||
production_action=$(echo "$CONFIG" | jq -r '."production action" // empty') | ||
if [ ! -z "$production_action" ]; then | ||
bashio::addon.option 'meters[1].action' "$production_action" | ||
echo -e "\e[33mMoved production action to meters configuration\e[0m" | ||
fi | ||
|
||
if [ ! -z "$consumption_prm" ] || [ ! -z "$consumption_token" ] || [ ! -z "$consumption_name" ] || [ ! -z "$consumption_action" ] || [ ! -z "$production_prm" ] || [ ! -z "$production_token" ] || [ ! -z "$production_name" ] || [ ! -z "$production_action" ]; then | ||
bashio::addon.option '"consumption PRM"' | ||
bashio::addon.option '"consumption token"' | ||
bashio::addon.option '"consumption name"' | ||
bashio::addon.option '"consumption action"' | ||
bashio::addon.option '"production PRM"' | ||
bashio::addon.option '"production token"' | ||
bashio::addon.option '"production name"' | ||
bashio::addon.option '"production action"' | ||
echo -e "\e[33mRestarting add-on\e[0m" | ||
bashio::addon.restart | ||
fi | ||
|
||
# Run HA Linky | ||
node --experimental-modules dist/index.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { expect, it, vi, describe, beforeEach } from 'vitest'; | ||
import { getUserConfig } from './config.js'; | ||
import { readFileSync } from 'node:fs'; | ||
|
||
vi.mock('node:fs', () => ({ | ||
readFileSync: vi.fn(), | ||
})); | ||
|
||
describe('getUserConfig', () => { | ||
beforeEach(() => { | ||
vi.mocked(readFileSync).mockReset(); | ||
}); | ||
|
||
it('Parses basic config correctly', () => { | ||
vi.mocked(readFileSync).mockReturnValue(`{ | ||
"meters": [ | ||
{ "prm": "123", "token": "ccc", "name": "Conso", "action": "sync" }, | ||
{ "prm": "123", "token": "ppp", "name": "Prod", "action": "reset", "production": true } | ||
] | ||
}`); | ||
expect(getUserConfig()).toEqual({ | ||
meters: [ | ||
{ action: 'sync', name: 'Conso', prm: '123', production: false, token: 'ccc' }, | ||
{ action: 'reset', name: 'Prod', prm: '123', production: true, token: 'ppp' }, | ||
], | ||
}); | ||
}); | ||
|
||
it('Throws if a PRM is configured multiple times', () => { | ||
vi.mocked(readFileSync).mockReturnValue(`{ | ||
"meters": [ | ||
{ "prm": "123", "token": "ccc", "name": "Conso", "action": "sync" }, | ||
{ "prm": "123", "token": "ppp", "name": "Prod", "action": "reset", "production": true }, | ||
{ "prm": "123", "token": "ddd", "name": "Clone", "action": "sync", "production": false } | ||
] | ||
}`); | ||
|
||
expect(() => getUserConfig()).toThrowError('PRM 123 is configured multiple times in consumption mode'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,55 @@ | ||
import { readFileSync } from 'fs'; | ||
import { readFileSync } from 'node:fs'; | ||
|
||
export type MeterConfig = { | ||
prm: string; | ||
token: string; | ||
name: string; | ||
action: 'sync' | 'reset'; | ||
isProduction: boolean; | ||
production: boolean; | ||
}; | ||
|
||
export type UserConfig = { | ||
consumption?: MeterConfig; | ||
production?: MeterConfig; | ||
}; | ||
export type UserConfig = { meters: MeterConfig[] }; | ||
|
||
export function getUserConfig(): UserConfig { | ||
let parsed: { meters?: any[] } = {}; | ||
|
||
try { | ||
const parsed: { | ||
'consumption PRM'?: string; | ||
'consumption token'?: string; | ||
'consumption name'?: string; | ||
'consumption action'?: string; | ||
'production PRM'?: string; | ||
'production token'?: string; | ||
'production name'?: string; | ||
'production action'?: string; | ||
} = JSON.parse(readFileSync('/data/options.json', 'utf8')); | ||
|
||
return { | ||
consumption: | ||
parsed['consumption PRM'] && parsed['consumption token'] | ||
? { | ||
prm: parsed['consumption PRM'], | ||
token: parsed['consumption token'], | ||
name: parsed['consumption name'] || 'Linky consumption', | ||
action: parsed['consumption action'] === 'reset' ? 'reset' : 'sync', | ||
isProduction: false, | ||
} | ||
: undefined, | ||
production: | ||
parsed['production PRM'] && parsed['production token'] | ||
? { | ||
prm: parsed['production PRM'], | ||
token: parsed['production token'], | ||
name: parsed['production name'] || 'Linky production', | ||
action: parsed['production action'] === 'reset' ? 'reset' : 'sync', | ||
isProduction: true, | ||
} | ||
: undefined, | ||
}; | ||
parsed = JSON.parse(readFileSync('/data/options.json', 'utf8')); | ||
} catch (e) { | ||
throw new Error('Cannot read user configuration: ' + e.toString()); | ||
} | ||
|
||
const result: UserConfig = { meters: [] }; | ||
|
||
if (parsed.meters && Array.isArray(parsed.meters) && parsed.meters.length > 0) { | ||
for (const meter of parsed.meters) { | ||
if (meter.prm && meter.token) { | ||
result.meters.push({ | ||
prm: meter.prm.toString(), | ||
token: meter.token, | ||
name: meter.name || 'Linky', | ||
action: meter.action === 'reset' ? 'reset' : 'sync', | ||
production: meter.production === true, | ||
}); | ||
} | ||
} | ||
} | ||
|
||
for (const m in result.meters) { | ||
for (const n in result.meters) { | ||
if ( | ||
m !== n && | ||
result.meters[m].prm === result.meters[n].prm && | ||
result.meters[m].production === result.meters[n].production | ||
) { | ||
throw new Error( | ||
`PRM ${result.meters[m].prm} is configured multiple times in ${ | ||
result.meters[m].production ? 'production' : 'consumption' | ||
} mode`, | ||
); | ||
} | ||
} | ||
} | ||
|
||
return result; | ||
} |
Oops, something went wrong.