Skip to content

ctg-tme/Memory-Storage-Functions-V2

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Memory-Storage-Functions-V2

MemoryStorage is a helper class for Cisco RoomOS devices that provides a simple, persistent key–value store for macros. It uses a dedicated “storage macro” on the device to store data across reboots and macro restarts.

This README focuses on:

  • How to use MemoryStorage from your own macros.
  • The public API (methods and behavior).
  • How storage is structured.
  • Error codes and how to handle them.

1. Overview

What this does

  • Provides per‑macro persistent storage:
    • memory.read(key) / memory.write(key, value)
    • Data is stored under a unique UUID key tied to the macro’s name.
  • Provides global persistent storage shared across macros:
    • memory.global.read(key)
    • memory.global.write(key, value)

All data is stored in a dedicated “storage macro” on the device, so it survives:

  • Device reboot
  • Macro engine restart
  • Macro edits/updates (as long as the macro name stays consistent)

2. Installation & Setup

MemoryStorage is a helper class for Cisco RoomOS devices that provides a simple, persistent key–value store for macros. It uses a dedicated “storage macro” on the device to store data across reboots and macro restarts.

This README focuses on:

  • How to use MemoryStorage from your own macros.
  • The public API (methods and behavior).
  • How storage is structured.
  • Error codes and how to handle them.

1. Overview

What this does

  • Provides per‑macro persistent storage:
    • memory.read(key) / memory.write(key, value)
    • Data is stored under a unique UUID key tied to the macro’s name.
  • Provides global persistent storage shared across macros:
    • memory.global.read(key)
    • memory.global.write(key, value)

All data is stored in a dedicated “storage macro” on the device, so it survives:

  • Device reboot
  • Macro engine restart
  • Macro edits/updates (as long as the macro name stays consistent)

2. Installation & Setup

2.1. Requirements

  • Cisco RoomOS device with macros enabled.
  • Access to the Macro Editor or equivalent API (e.g., xAPI).
  • A suitable xapi object available in your macro environment.

2.2. Creating/Importing the MemoryStorage macro

  1. Add the MemoryStorage code to a macro file, for example:
    • Memory-Storage-Functions.js
  2. Ensure your macro that wants to use it:
    • Either imports it (if your environment supports module syntax), or
    • Has the class in the same macro file.

Note: The exact import/usage pattern may depend on your RoomOS macro environment. The class is exported as:

export { MemoryStorage };


3. Quick Start

3.1. Initialize MemoryStorage in your macro

In your macro:

import xapi from 'xapi';
import { MemoryStorage } from './Memory-Storage-Functions.js';  // adjust path as needed

const memory = new MemoryStorage(xapi, {
  // Optional: customize the storage macro name prefix
  // StorageMacroName: 'MySolution'
});

async function initMemory() {
  const result = await memory.init();
  console.log(`Memory initialized with storage key: ${result.Storage_KeyName}`);
}

initMemory();
  • init() must be called (and resolved) before using read, write, or global methods.
  • If the storage macro does not exist yet, it will be created automatically.

4. Storage Model

4.1. Storage Macro Name

When you construct MemoryStorage:

  • If you pass options.StorageMacroName, the storage macro name becomes:
    • <StorageMacroName>-Storage
    • Example: { StorageMacroName: 'MySolution' }MySolution-Storage
  • Otherwise, the default storage macro name is:
    • Memory-Storage

4.2. Internal Structure (Conceptual)

The storage macro content is a JavaScript file that looks like:

const memory = {
  "$_CRITICAL_WARNINGS": [ /* ... */ ],
  "$_About_Memory_Storage": [ /* ... */ ],
  "$_MACRO_UUID_MAP": {
    "<MacroNameA>": "#_<uuidA>_<MacroNameA>",
    "<MacroNameB>": "#_<uuidB>_<MacroNameB>"
  },
  "#_<uuidA>_<MacroNameA>": {
    // per-macro data for MacroNameA
    "someKey": "someValue"
  },
  "#_<uuidB>_<MacroNameB>": {
    // per-macro data for MacroNameB
  },
  // Global keys (shared across macros) live at the top level:
  "GlobalKey1": { /* ... */ },
  "GlobalKey2": "some string"
};
  • Do not edit this storage macro by hand.
  • All interaction should go through the MemoryStorage API.

5. Public API

5.1. Constructor

const memory = new MemoryStorage(XAPIObject, options);

Parameters:

  • XAPIObject
    The xapi object from the RoomOS macro environment.

  • options (optional)

    • StorageMacroName (string): A base name for the storage macro. The actual macro created will be:
      • StorageMacroName + '-Storage'

Examples:

const memory = new MemoryStorage(xapi);
// -> Uses default storage macro name: 'Memory-Storage'

const memoryCustom = new MemoryStorage(xapi, { StorageMacroName: 'MySolution' });
// -> Uses storage macro name: 'MySolution-Storage'

5.2. init()

await memory.init();

Initializes the storage system:

  • Validates the xapi object.
  • Tries to read the storage macro:
    • If present, parses its contents.
    • If not present, creates a new storage macro with initial metadata and an entry for this macro.
  • Ensures this macro has a unique UUID‑based key for its per‑macro data.
  • Marks MemoryStorage as initialized.

Returns:

A promise resolving to:

{
  Status: 'OK',
  Storage_KeyName: '#_<uuid>_<ActiveMacroName>'
}

Must be called before:

  • memory.read(...)
  • memory.write(...)
  • memory.global.read(...)
  • memory.global.write(...)

If you call those methods before init() has completed, you will get a “Memory not initialized” error.


5.3. Per‑Macro Methods

These methods read/write data in the namespace unique to the current macro (ActiveMacroName).

5.3.1. read(key)

const value = await memory.read('myKey');

Behavior:

  • Re-loads the current storage content from the storage macro.
  • Locates this macro’s namespace using the internal UUID key (e.g. #_<uuid>_<MacroName>).
  • Reads myKey within that per‑macro object.

Throws if:

  • init() has not been successfully called.
  • The parent key for this macro is missing in storage.
  • key does not exist for this macro.

Example:

try {
  const threshold = await memory.read('AlertThreshold');
  console.log(`Threshold is: ${threshold}`);
} catch (e) {
  console.error('Failed to read from memory:', e.message, e.code);
}

5.3.2. write(key, value)

await memory.write('myKey', myValue);

Behavior:

  • Re-loads the current storage content from the storage macro.
  • Ensures this macro’s per‑macro object exists.
  • Writes value to myKey inside this macro’s namespace.
  • Persists the updated storage back to the storage macro.

Throws if:

  • init() has not been successfully called.
  • There is a problem saving the storage macro.

Example:

try {
  await memory.write('AlertThreshold', 5);
  console.log('AlertThreshold saved.');
} catch (e) {
  console.error('Failed to write to memory:', e.message, e.code);
}

5.4. Global Methods

These methods work on the top-level of the storage object and are shared across all macros using the same storage macro.

5.4.1. global.read(key)

const value = await memory.global.read('GlobalSetting');

Behavior:

  • Re-loads the storage object.
  • Reads the top‑level key GlobalSetting.

Throws if:

  • init() has not been successfully called.
  • key is not found at the top level of the storage object.

Example:

try {
  const cfg = await memory.global.read('SharedConfig');
  console.log('SharedConfig:', cfg);
} catch (e) {
  console.error('Global read failed:', e.message, e.code);
}

5.4.2. global.write(key, value)

await memory.global.write('GlobalSetting', value);

Behavior:

  • Re-loads the storage object.
  • Validates that the key name does not start with $ or $_ (reserved for internal metadata).
  • Writes value to the top‑level key GlobalSetting.
  • Persists the updated storage.

Throws if:

  • init() has not been successfully called.
  • The key starts with $ or $_.
  • Saving fails.

Example:

try {
  await memory.global.write('SharedConfig', { enabled: true, mode: 'auto' });
  console.log('SharedConfig updated.');
} catch (e) {
  console.error('Global write failed:', e.message, e.code);
}

6. Error Codes

Most errors thrown by MemoryStorage are instances of Error with an additional code property. The message also embeds the code in the form || MacroErrorCode: <code>.

Example error object:

{
  message: "Unable to run .read() method. Memory not initialized || MacroErrorCode: msfv2.r.1",
  code: "msfv2.r.1"
}

6.1. General Pattern

  • All codes start with msfv2.
  • Private method errors typically include the method initials (_te, _vxo, _wafc, etc.).
  • Public API errors have concise codes (r, w, g-r, g-w).
  • Suffix .1, .2, .3 indicate different error cases within the same area.

You can use error.code to programmatically handle specific cases.


6.2. Error Code Reference (by area)

6.2.1. Core / Internal

  • msfv2._te.1
    Attempted to call _throwError without a valid internal token. Indicates internal misuse, not expected in normal macro usage.

  • msfv2._vxo.1
    _validateXapiObject called without token. Internal misuse.

  • msfv2._vxo.2
    xapi object is not defined or is not an object.

  • msfv2._vxo.3
    xapi.Config property is invalid or missing.

  • msfv2._wafc.1
    _wrapAndFormatContent called without token.


6.2.2. Parsing & Storage Format

  • msfv2._ps.1
    _parseStorage called without token.

  • msfv2._ps.2
    Not an error code; this is a log message when a trailing semicolon is removed.

  • msfv2._ps.3
    Failed to parse the storage macro content after trying all known patterns.

    • Usually indicates manual modification or corruption of the storage macro.

6.2.3. UUID / Internal Helpers

  • msfv2._gu.1
    _generateUUID called without token. Internal misuse.

6.2.4. Fetching & Saving Storage Macro

  • msfv2._gmo.1
    _getMemoryObject called without token.

  • msfv2._ssm.1
    _saveStorageMacro called without token.

  • msfv2._ssm.2
    Failure while saving the storage macro via xapi.Command.Macros.Macro.Save.

    • The error message will include the original e.message and e.code.
  • msfv2._fsm.1
    _fetchStorageMacro called without token.

  • msfv2._fsm.2
    _fetchStorageMacro called without a target name.

  • msfv2._fsm.3
    Storage macro is missing (xAPI Get returned code 1).

    • In init(), this is handled by creating a new storage macro.
  • msfv2._fsm.4
    Malformed xCommand (e.g., invalid parameters) for Macros Macro Get.

  • msfv2._fsm.5
    Unknown error returned from xapi.Command.Macros.Macro.Get.


6.2.5. Initialization

  • msfv2._csm.1
    _createStorageMacro called without token.

  • msfv2._ps.3
    May surface during init() if the storage macro is corrupted or manually edited.

  • msfv2._fsm.3
    In init(), indicates storage macro not found; triggers auto‑creation.

  • Any underlying error code from fetch/parse/save may be re-wrapped with message:
    Failed to Initialize memory.


6.2.6. Per‑Macro Read/Write

  • msfv2.r.1
    .read() called before initialization.

  • msfv2.r.2
    Parent key (this macro’s UUID‑based storage object) not found in storage.

    • This can indicate tampering with the storage macro or unexpected deletion of this macro’s data.
  • msfv2.r.3
    Requested key not found within this macro’s storage.

  • msfv2.w.1
    .write() called before initialization.


6.2.7. Global Read/Write

  • msfv2._gr.1
    _globalRead called without token (internal misuse).

  • msfv2._gr.2
    _globalRead invoked while memory is not initialized.

  • msfv2._gr.3
    The requested global key does not exist in the storage macro.

  • msfv2._gw.1
    _globalWrite called without token (internal misuse).

  • msfv2._gw.2
    _globalWrite invoked while memory is not initialized.

  • msfv2._gw.3
    Attempted to use a global key starting with $ or $_.

    • These prefixes are reserved for internal metadata keys (like $_MACRO_UUID_MAP).
  • msfv2._gw.4
    Global write attempted with a # or #_ prefixed key without options.Override = true; these keys are reserved for other solutions’ data.


7. Recommended Usage Patterns

7.1. Always guard with try/catch

Because all operations are async and can throw, always use try/catch around init, read, and write:

async function setup() {
  try {
    await memory.init();
  } catch (e) {
    console.error('Memory initialization failed:', e.message, e.code);
    // Optionally, decide whether to continue or abort
  }
}

async function useMemory() {
  try {
    await memory.write('ExampleKey', 'some value');
    const v = await memory.read('ExampleKey');
    console.log('ExampleKey:', v);
  } catch (e) {
    console.error('Memory operation failed:', e.message, e.code);
  }
}

8. Operational Notes

  • Do not edit the storage macro manually.
    Manual edits can break JSON parsing and cause msfv2._ps.3 or other initialization errors.

  • Macro name changes
    The mapping is based on the macro’s active name (ActiveMacroName). Renaming the main macro may result in a new UUID mapping and a different per‑macro namespace.

  • Unsupported by TAC
    As captured in the created storage macro’s metadata, this is a custom solution and is not supported by Cisco TAC.


Error Code Definitions

Error Code Function Location Description Suggested Action
msfv2.g-r.1 global.read Public API Attempted .global.read() before memory was initialized.
msfv2.g-w.1 global.write Public API Attempted .global.write() before memory was initialized.
msfv2.r.1 read Public API Attempted .read() before memory was initialized.
msfv2.r.2 read Public API This macro’s parent key (_macroKeyName) was not found in the storage macro.
msfv2.r.3 read Public API Requested key not found in this macro’s storage object.
msfv2.w.1 write Public API Attempted .write() before memory was initialized.
msfv2._te.1 _throwError Internal _throwError was called without a valid internal token (indicates internal misuse).
msfv2._vxo.1 _validateXapiObject Internal _validateXapiObject was called without a valid internal token.
msfv2._vxo.2 _validateXapiObject Internal XAPI object is not defined or not an object.
msfv2._vxo.3 _validateXapiObject Internal XAPI.Config is invalid or missing.
msfv2._wafc.1 _wrapAndFormatContent Internal _wrapAndFormatContent was called without a valid internal token.
msfv2._ps.1 _parseStorage Internal _parseStorage was called without a valid internal token.
msfv2._ps.3 _parseStorage Internal Failed to parse the storage macro content after trying all supported patterns.
msfv2._gu.1 _generateUUID Internal _generateUUID was called without a valid internal token.
msfv2._gmo.1 _getMemoryObject Internal _getMemoryObject was called without a valid internal token.
msfv2._ssm.1 _saveStorageMacro Internal _saveStorageMacro was called without a valid internal token.
msfv2._ssm.2 _saveStorageMacro Internal Failed to save the storage macro via XAPI.Command.Macros.Macro.Save.
msfv2._fsm.1 _fetchStorageMacro Internal _fetchStorageMacro was called without a valid internal token.
msfv2._fsm.2 _fetchStorageMacro Internal _fetchStorageMacro was called without a target storage macro name.
msfv2._fsm.3 _fetchStorageMacro Internal / init Target storage macro not found on the device.
msfv2._fsm.4 _fetchStorageMacro Internal Malformed xCommand Macros Macro Get (invalid parameters or similar).
msfv2._fsm.5 _fetchStorageMacro Internal Unknown error occurred while performing xCommand Macros Macro Get.
msfv2._csm.1 _createStorageMacro Internal _createStorageMacro was called without a valid internal token.
msfv2._gr.1 _globalRead Internal _globalRead was called without a valid internal token (should use global.read()).
msfv2._gr.2 _globalRead Internal Attempted _globalRead() while memory was not initialized.
msfv2._gr.3 _globalRead Internal Requested global key not found in the storage macro.
msfv2._gw.1 _globalWrite Internal _globalWrite was called without a valid internal token (should use global.write()).
msfv2._gw.2 _globalWrite Internal Attempted _globalWrite() while memory was not initialized.
msfv2._gw.3 _globalWrite Internal Global write attempted with a key starting with $ or $_, which is prohibited.
msfv2._gw.4 _globalWrite Internal Global write attempted with a # or #_ prefixed key without options.Override = true; these keys are reserved for other data.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published