The chat responses are generated using Generative AI technology for intuitive search and may not be entirely accurate. They are not intended as professional advice. For full details, including our use rights, privacy practices and potential export control restrictions, please refer to our Generative AI Service Terms of Use and Generative AI Service Privacy Information. As this is a test version, please let us know if something irritating comes up. Like you get recommended a chocolate fudge ice cream instead of an energy managing application. If that occurs, please use the feedback button in our contact form!
Skip to content
Industrial IoT Open Source Tools and Libraries

Demo applications, libraries and SDKs as well as useful connectivity tools which are maintained and released as open source software.

Mindconnect-NodeJS - Agent Development - Agent State Storage¶

Introduction¶

The agents need to manage their state information over time. This state information consists of

  • agent secrets
  • agent configuration
  • agent mappings
  • history of agent secrets
  • list of uploaded files and corresponding eTags (so that agents can overwrite the files if necessary)

This information needs to be persisted over time.

Info

The agents store the eTag of the file so that they can overwrite these files in the future. This will change once agents can read the eTags of the files.

Storage Provider - Default Implementation¶

The default implementation stores the state in the hidden .mc directory in the root directory of your project.

ls -la .mc

total 8
drwxr-xr-x 1 sn0wcat 1049089    0 May 17 17:41 .
drwxr-xr-x 1 sn0wcat 1049089    0 May 17 17:41 ..
-rw-r--r-- 1 sn0wcat 1049089 2814 May 17 17:41 8ed19ef5515542b4bb05842bfbd48f38.json

Storing the data using different storage provider¶

If you need to store the data in a different or more secure fashion you can provide your own implementation of the StorageProvider. You need to implement the following interface

/**
 * Per default, the library stores the agent settings in the directory .mc
 * You can pass a class which implements a ConfigurationStorage in the constructor if you want to store
 * the settings somewhere else. (e.g. database, encrypted file system etc)
 * @export
 * @interface ConfigurationStorage
 */
export interface IConfigurationStorage {
    GetConfig(config: IMindConnectConfiguration): IMindConnectConfiguration;
    SaveConfig(config: IMindConnectConfiguration): Promise<IMindConnectConfiguration>;
}

The GetConfig method should check if the config has changed and return no value so that the agent can be onboarded again

if (_.isEqual(json.content, configuration.content)) {
    return json;
} else {
    log("The configuration has changed we will onboard again.");
}

Example¶

export class MySecureStorage implements IConfigurationStorage {
    private lock: AsyncLock;

    private encrypt(): string {
        //... your secure implementation
    }

    private decrypt(): string {
        //... your secure implementation
    }

    public GetConfig(configuration: IMindConnectConfiguration): IMindConnectConfiguration {
        try {
            const json = <IMindConnectConfiguration>(
                const result = fs.readFileSync (path.resolve(`${this._basePath}/${configuration.content.clientId}.bin`));
                return this.decrypt(result);
            );
            if (_.isEqual(json.content, configuration.content)) {
                return json;
            } else {
                log("The configuration has changed we will onboard again.");
            }
        } catch (err) {
            log(`There is no configuration stored yet for agent with id ${configuration.content.clientId}`);
        }

        return configuration;
    }

    public async SaveConfig(config: IMindConnectConfiguration): Promise<IMindConnectConfiguration> {
        const fileName = `${this._basePath}/${config.content.clientId}.bin`;
        return await this.lock.acquire(fileName, () => {
            const data = JSON.stringify(config);
            fs.writeFileSync(fileName, this.encrypt(data));
            return config;
        });
    }

    constructor(private _basePath: string) {
        if (!fs.existsSync(this._basePath)) {
            fs.mkdirSync(this._basePath);
        }

        this.lock = new AsyncLock({});
    }
}

Using your storage¶

You can pass the instance of your storage provider to the MindConnectAgent constructor.

const agent = new MindConnectAgent(configuration, undefined, new MySecureStorage());