[APP][Pro] AWTRIX Light - Connected Smart Clock for your Smart Home

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();
1 Like