Thanks for idea @Bckp to re-use script [HOW-TO][Pro][Cloud] - Tool to FIX (advanced) flows after removing and re-adding devices and thanks @martijnpoppen for your support, I was able to modify it to do the replacement only in Flows with defined FlowID… let me share it in case someone would have similar challenge…
// It's recommended to only use 1 id at a time. This will also fix your variables.
const oldIds = ['oldId of device'];
const newIds = ['newId of device'];
const specificFlowIds = ['flow-id-1', 'flow-id-2', 'flow-id-3']; // Add the specific flow IDs here
// Set the softRun variable to true or false to determine whether changes should be logged or actually executed
const softRun = true; // true | false
// Open the console in your browser and the result will be shown there
// Howto open console: https://balsamiq.com/support/faqs/browserconsole/
const main = async function () {
console.log('Starting main function...');
// Retrieve all of the existing flows
const flows = await Homey.flow.getFlows();
// Iterate through each flow
Object.values(flows).forEach(async (f) => {
console.log(`Flow "${f.name}" with ID "${f.id}" is being checked.`);
if (!specificFlowIds.includes(f.id)) {
return;
}
console.log(`Checking flow "${f.name}"...`);
// If the flow has a trigger with a URI or ID
if (f.trigger && (f.trigger.uri || f.trigger.id)) {
const trigger = f.trigger;
let replaceValue = '';
let cardsChanged = false;
if (oldIds.length === 1) {
replaceValue = oldIds[0];
} else if (trigger.uri && trigger.uri.includes('homey:device:')) {
replaceValue = trigger.uri.replace('homey:device:', '');
} else if (trigger.id && trigger.id.includes('homey:device:')) {
replaceValue = trigger.id.replace('homey:device:', '');
}
if (replaceValue.includes('|')) {
replaceValue = replaceValue.split('|')[0];
} else if (replaceValue.includes(':')) {
replaceValue = replaceValue.split(':')[0];
}
console.log(`Checking IDs in flow "${f.name}": Replace value found - ${replaceValue}`);
// If the flow contains the old device ID
if (oldIds.includes(replaceValue)) {
const replacer = new RegExp(replaceValue, 'g');
const index = oldIds.findIndex((o) => o.includes(replaceValue));
// Replace the old device ID with the corresponding new device ID in the trigger
if (trigger.uri) {
const oldToken = trigger.uri;
trigger.uri = oldToken.replace(replacer, newIds[index]);
if (oldToken !== trigger.uri) {
console.log(`URI change detected. Old: ${oldToken}, New: ${trigger.uri}`);
cardsChanged = true;
}
} else if (trigger.id) {
const oldToken = trigger.id;
trigger.id = oldToken.replace(replacer, newIds[index]);
if (oldToken !== trigger.id) {
console.log(`ID change detected. Old: ${oldToken}, New: ${trigger.id}`);
cardsChanged = true;
}
}
if (trigger.droptoken) {
const oldToken = trigger.droptoken;
trigger.droptoken = oldToken.replace(replacer, newIds[index]);
if (oldToken !== trigger.droptoken) {
console.log(`Droptoken change detected. Old: ${oldToken}, New: ${trigger.droptoken}`);
cardsChanged = true;
}
}
if (cardsChanged) {
console.log(`Preparing to update flow "${f.name}"...`);
if (!softRun) {
try {
const response = await Homey.flow.updateFlow({
id: f.id,
flow: { id: f.id, trigger: trigger }
});
console.log(`Update response: ${JSON.stringify(response)}`);
} catch (error) {
console.error(`Error updating flow "${f.name}":`, error);
}
} else {
console.log(`Would update flow "${f.name}" with new trigger:`, {
id: f.id,
flow: { id: f.id, trigger: trigger }
});
}
}
}
}
console.log(`Checking actions in flow "${f.name}"`);
// Iterate through each action in the flow
f.actions.forEach(async (a, i) => {
let replaceValue = '';
let cardsChanged = false;
if (oldIds.length === 1) {
replaceValue = oldIds[0];
} else if (a.uri && a.uri.includes('homey:device:')) {
replaceValue = a.uri.replace('homey:device:', '');
} else if (a.id && a.id.includes('homey:device:')) {
replaceValue = a.id.replace('homey:device:', '');
}
if (replaceValue.includes('|')) {
replaceValue = replaceValue.split('|')[0];
} else if (replaceValue.includes(':')) {
replaceValue = replaceValue.split(':')[0];
}
if (oldIds.includes(replaceValue)) {
const replacer = new RegExp(replaceValue, 'g');
const actions = f.actions;
const index = oldIds.findIndex((o) => o.includes(replaceValue));
if (actions[i].uri) {
const oldToken = actions[i].uri;
actions[i].uri = oldToken.replace(replacer, newIds[index]);
if (oldToken !== actions[i].uri) {
console.log(`URI change detected in action. Old: ${oldToken}, New: ${actions[i].uri}`);
cardsChanged = true;
}
} else if (actions[i].id) {
const oldToken = actions[i].id;
actions[i].id = oldToken.replace(replacer, newIds[index]);
if (oldToken !== actions[i].id) {
console.log(`ID change detected in action. Old: ${oldToken}, New: ${actions[i].id}`);
cardsChanged = true;
}
}
if (actions[i].args && actions[i].args.value && typeof actions[i].args.value === 'string') {
const oldToken = actions[i].args.value;
actions[i].args.value = oldToken.replace(replacer, newIds[index]);
if (oldToken !== actions[i].args.value) {
console.log(`Value change detected in action args. Old: ${oldToken}, New: ${actions[i].args.value}`);
cardsChanged = true;
}
}
if (cardsChanged) {
console.log(`Preparing to update actions in flow "${f.name}"...`);
if (!softRun) {
try {
const response = await Homey.flow.updateFlow({
id: f.id,
flow: { id: f.id, actions: actions }
});
console.log(`Update response: ${JSON.stringify(response)}`);
} catch (error) {
console.error(`Error updating actions in flow "${f.name}":`, error);
}
} else {
console.log(`Would update actions in flow "${f.name}" with:`, {
id: f.id,
flow: { id: f.id, actions: actions }
});
}
}
}
});
console.log(`Checking conditions in flow "${f.name}"`);
// Iterate through each condition in the flow
f.conditions.forEach(async (a, i) => {
let replaceValue = '';
let cardsChanged = false;
if (oldIds.length === 1) {
replaceValue = oldIds[0];
} else if (a.uri && a.uri.includes('homey:device:')) {
replaceValue = a.uri.replace('homey:device:', '');
} else if (a.id && a.id.includes('homey:device:')) {
replaceValue = a.id.replace('homey:device:', '');
}
if (replaceValue.includes('|')) {
replaceValue = replaceValue.split('|')[0];
} else if (replaceValue.includes(':')) {
replaceValue = replaceValue.split(':')[0];
}
if (oldIds.includes(replaceValue)) {
const replacer = new RegExp(replaceValue, 'g');
const conditions = f.conditions;
const index = oldIds.findIndex((o) => o.includes(replaceValue));
if (conditions[i].uri) {
const oldToken = conditions[i].uri;
conditions[i].uri = oldToken.replace(replacer, newIds[index]);
if (oldToken !== conditions[i].uri) {
console.log(`URI change detected in condition. Old: ${oldToken}, New: ${conditions[i].uri}`);
cardsChanged = true;
}
} else if (conditions[i].id) {
const oldToken = conditions[i].id;
conditions[i].id = oldToken.replace(replacer, newIds[index]);
if (oldToken !== conditions[i].id) {
console.log(`ID change detected in condition. Old: ${oldToken}, New: ${conditions[i].id}`);
cardsChanged = true;
}
}
if (cardsChanged) {
console.log(`Preparing to update conditions in flow "${f.name}"...`);
if (!softRun) {
try {
const response = await Homey.flow.updateFlow({
id: f.id,
flow: { id: f.id, conditions: conditions }
});
console.log(`Update response: ${JSON.stringify(response)}`);
} catch (error) {
console.error(`Error updating conditions in flow "${f.name}":`, error);
}
} else {
console.log(`Would update conditions in flow "${f.name}" with:`, {
id: f.id,
flow: { id: f.id, conditions: conditions }
});
}
}
}
});
});
// Enhanced logging for advanced flows
// Enhanced logging for advanced flows
console.log('--------------------------------------');
// Retrieve all of the existing advanced flows
const advanced_flows = Object.values(await Homey.flow.getAdvancedFlows());
console.log(`Checking advanced flows. Total count: ${advanced_flows.length}`);
// Iterate through each advanced flow
advanced_flows.forEach(async (af) => {
if (!specificFlowIds.includes(af.id)) {
console.log(`Advanced flow "${af.name}" with ID "${af.id}" not in specific flow IDs list.`);
return;
}
console.log(`Checking advanced flow "${af.name}" with ID "${af.id}"...`);
const cards = af.cards;
let cardsChanged = false;
// Iterate through each card in the advanced flow
for (const c in cards) {
let replaceValue = null;
console.log(`Checking card ID "${c}" in advanced flow "${af.name}"...`);
if (oldIds.length === 1) {
replaceValue = oldIds[0];
} else if (cards[c].ownerUri && cards[c].ownerUri.includes('homey:device:')) {
replaceValue = cards[c].ownerUri.replace('homey:device:', '');
}
if (replaceValue && replaceValue.includes('|')) {
replaceValue = replaceValue.split('|')[0];
} else if (replaceValue && replaceValue.includes(':')) {
replaceValue = replaceValue.split(':')[0];
}
console.log(`Replace value: ${replaceValue}`);
const replacer = new RegExp(replaceValue, 'g');
const index = oldIds.findIndex((o) => o.includes(replaceValue));
if (index === -1) {
console.log(`No matching old ID found in card ID "${c}" of advanced flow "${af.name}".`);
continue;
}
console.log(`Card ID "${c}" has replace value "${replaceValue}". Proceeding with replacement...`);
if (cards[c].args && cards[c].droptoken) {
const oldToken = cards[c].droptoken;
cards[c].droptoken = oldToken.replace(replacer, newIds[index]);
if (oldToken !== cards[c].droptoken) {
console.log(`Droptoken change detected in advanced flow card. Old: ${oldToken}, New: ${cards[c].droptoken}`);
cardsChanged = true;
}
}
if (cards[c].args && cards[c].args.value && typeof cards[c].args.value === 'string') {
const oldToken = cards[c].args.value;
cards[c].args.value = oldToken.replace(replacer, newIds[index]);
if (oldToken !== cards[c].args.value) {
console.log(`Value change detected in advanced flow card args. Old: ${oldToken}, New: ${cards[c].args.value}`);
cardsChanged = true;
}
}
if (cards[c].args && cards[c].args.text && typeof cards[c].args.text === 'string') {
const oldToken = cards[c].args.text;
cards[c].args.text = oldToken.replace(replacer, newIds[index]);
if (oldToken !== cards[c].args.text) {
console.log(`Text change detected in advanced flow card args. Old: ${oldToken}, New: ${cards[c].args.text}`);
cardsChanged = true;
}
}
if (cards[c].args && cards[c].args.message && typeof cards[c].args.message === 'string') {
const oldToken = cards[c].args.message;
cards[c].args.message = oldToken.replace(replacer, newIds[index]);
if (oldToken !== cards[c].args.message) {
console.log(`Message change detected in advanced flow card args. Old: ${oldToken}, New: ${cards[c].args.message}`);
cardsChanged = true;
}
}
if (cards[c].ownerUri) {
const oldToken = cards[c].ownerUri;
cards[c].ownerUri = cards[c].ownerUri.replace(replacer, newIds[index]);
if (oldToken !== cards[c].ownerUri) {
console.log(`OwnerUri change detected in advanced flow card. Old: ${oldToken}, New: ${cards[c].ownerUri}`);
cardsChanged = true;
}
}
if (cards[c].id) {
const oldToken = cards[c].id;
cards[c].id = cards[c].id.replace(replacer, newIds[index]);
if (oldToken !== cards[c].id) {
console.log(`ID change detected in advanced flow card. Old: ${oldToken}, New: ${cards[c].id}`);
cardsChanged = true;
}
}
// Apply changes to nested properties within args
if (cards[c].args) {
for (const arg in cards[c].args) {
if (typeof cards[c].args[arg] === 'string') {
const oldToken = cards[c].args[arg];
cards[c].args[arg] = oldToken.replace(replacer, newIds[index]);
if (oldToken !== cards[c].args[arg]) {
console.log(`Change detected in card args.${arg} of advanced flow card. Old: ${oldToken}, New: ${cards[c].args[arg]}`);
cardsChanged = true;
}
} else if (typeof cards[c].args[arg] === 'object' && cards[c].args[arg] !== null) {
for (const subArg in cards[c].args[arg]) {
if (typeof cards[c].args[arg][subArg] === 'string') {
const oldToken = cards[c].args[arg][subArg];
cards[c].args[arg][subArg] = oldToken.replace(replacer, newIds[index]);
if (oldToken !== cards[c].args[arg][subArg]) {
console.log(`Change detected in card args.${arg}.${subArg} of advanced flow card. Old: ${oldToken}, New: ${cards[c].args[arg][subArg]}`);
cardsChanged = true;
}
}
}
}
}
}
}
// If any cards in the advanced flow were changed
if (cardsChanged) {
console.log(`Preparing to update advanced flow "${af.name}" with new cards...`);
if (!softRun) {
try {
const response = await Homey.flow.updateAdvancedFlow({
id: af.id,
advancedflow: { cards: cards }
});
console.log(`Update response for advanced flow "${af.name}": ${JSON.stringify(response)}`);
} catch (error) {
console.error(`Error updating advanced flow "${af.name}":`, error);
}
} else {
console.log(`Would update advanced flow "${af.name}" with new cards:`, {
id: af.id,
advancedflow: { cards: cards }
});
}
}
});
};
// Call the main function to execute the flow ID replacements
main();