### ESP32 FreeRTOS Setup and Loop Structure Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/README.md Demonstrates the basic FreeRTOS task structure for an ESP32 project. The setup function initializes components and starts tasks, while the loop function remains empty, relying on dedicated tasks for all operations. This pattern is common in embedded systems using RTOS. ```cpp void setup() { // Initialize components // Start maintenance task startMaintenanceTask(); // Delete main task after setup vTaskDelete(NULL); } void loop() { // All work done in dedicated tasks vTaskDelay(portMAX_DELAY); } ``` -------------------------------- ### Install and Run MCP Server Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Instructions for setting up and running the Model Context Protocol (MCP) server for AI assistant integration. This involves installing dependencies, configuring environment variables, and running the server. ```bash cd mcp-server pip install -e . python server.py export ENERGYME_BASE_URL="http://192.168.1.100" export ENERGYME_USERNAME="admin" export ENERGYME_PASSWORD="energyme" npx @modelcontextprotocol/inspector uv --directory . run server.py ``` -------------------------------- ### Install EnergyMe-Home MCP Server (Bash) Source: https://github.com/jibrilsharafi/energyme-home/blob/main/mcp-server/README.md Installs the EnergyMe-Home MCP server locally using pip. This command should be run from the 'mcp-server' directory. ```bash cd mcp-server pip install -e . ``` -------------------------------- ### Run EnergyMe-Home MCP Server (Python) Source: https://github.com/jibrilsharafi/energyme-home/blob/main/mcp-server/README.md Starts the EnergyMe-Home MCP server. This command executes the main server script. ```python python server.py ``` -------------------------------- ### Rollback to Previous Firmware Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Initiates a rollback to the previously installed firmware version. Requires authentication. ```bash curl -X POST "http://energyme.local/api/v1/ota/rollback" \ -H "Cookie: auth_token=YOUR_TOKEN" ``` -------------------------------- ### Home Assistant Integration Configuration Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Instructions and example for integrating EnergyMe-Home with Home Assistant. This involves installing the custom integration and configuring it, which then exposes energy measurements as Home Assistant entities. ```yaml # Home Assistant configuration (via UI integration) # 1. Install custom integration from HACS or manually # 2. Add integration via Settings > Integrations > Add Integration # 3. Enter device IP address (mDNS discovery coming soon) # All energy measurements become Home Assistant entities: # - sensor.energyme_channel_0_voltage # - sensor.energyme_channel_0_current # - sensor.energyme_channel_0_active_power # - sensor.energyme_channel_0_energy_imported # - etc. ``` -------------------------------- ### Home Assistant Integration Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Guide for integrating EnergyMe Home with Home Assistant using the custom integration. ```APIDOC ## Home Assistant Integration ### Description Integrate EnergyMe Home with your Home Assistant setup using the dedicated custom integration. ### Installation 1. **Via HACS**: Install the `homeassistant-energyme` custom integration through the Home Assistant Community Store (HACS). 2. **Manually**: Download the integration files and place them in your Home Assistant `custom_components` directory. ### Configuration 1. Navigate to **Settings > Integrations** in your Home Assistant UI. 2. Click **Add Integration**. 3. Search for and select the **EnergyMe Home** integration. 4. Enter the IP address of your EnergyMe Home device. (mDNS discovery is planned for future releases). ### Available Entities Once configured, all energy measurements from EnergyMe Home will be exposed as Home Assistant entities, including: - `sensor.energyme_channel_0_voltage` - `sensor.energyme_channel_0_current` - `sensor.energyme_channel_0_active_power` - `sensor.energyme_channel_0_energy_imported` - ...and other available measurements for each monitored channel. ``` -------------------------------- ### Event Listener Setup and Initialization Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/ade7953-tester.html Sets up event listeners for user interactions and initializes the application when the DOM is fully loaded. This includes setting up search, register selection, and button click handlers. ```javascript document.addEventListener('DOMContentLoaded', function() { setupEventListeners(); populateRegisterList(); filterRegisters(); }); function setupEventListeners() { // Search functionality searchInput.addEventListener('input', filterRegisters); // Register selection registerList.addEventListener('click', function(e) { const item = e.target.closest('.register-item'); if (item) selectRegister(item); }); // Action buttons readBtn.addEventListener('click', performRead); burstBtn.addEventListener('click', toggleBurstMode); writeBtn.addEventListener('click', performWrite); } ``` -------------------------------- ### Get and Set Log Levels via API Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Demonstrates how to retrieve the current log level and set new log levels (print and save) for the EnergyMe Home device using its REST API. Requires an authentication token. ```bash curl -X GET "http://energyme.local/api/v1/logs/level" \ -H "Cookie: auth_token=YOUR_TOKEN" curl -X PATCH "http://energyme.local/api/v1/logs/level" \ -H "Content-Type: application/json" \ -H "Cookie: auth_token=YOUR_TOKEN" \ -d '{"print": "DEBUG", "save": "WARNING"}' ``` -------------------------------- ### Start and Stop MQTT Auto-Reload Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/configuration.html Manages the interval for automatically reloading the MQTT status. `startCustomMqttAutoReload` sets up an interval to call `loadCustomMqttStatus` periodically if MQTT is enabled. `stopCustomMqttAutoReload` clears any existing interval. ```javascript function startCustomMqttAutoReload() { if (customMqttAutoReloadInterval) { clearInterval(customMqttAutoReloadInterval); } customMqttAutoReloadInterval = setInterval(() => { if (customMqttConfig && customMqttConfig.enabled) { loadCustomMqttStatus(); } }, AUTO_RELOAD_INTERVAL_MS); } function stopCustomMqttAutoReload() { if (customMqttAutoReloadInterval) { clearInterval(customMqttAutoReloadInterval); customMqttAutoReloadInterval = null; } } ``` -------------------------------- ### REST API: Configure Channel (Bash) Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Allows configuration of individual circuit channels on the EnergyMe-Home device. Supports partial updates (PATCH) for a single channel, retrieving all channel configurations (GET), and bulk updates (PUT) for multiple channels. Requires an authentication token. ```bash # Update channel configuration (partial update) curl -X PATCH "http://energyme.local/api/v1/ade7953/channel" \ -H "Content-Type: application/json" \ -H "Cookie: auth_token=YOUR_TOKEN" \ -d '{ "index": 1, "active": true, "reverse": false, "highPriority": true, "label": "Kitchen Circuit", "phase": 1, "ctSpecification": { "currentRating": 30.0, "voltageOutput": 0.333, "scalingFraction": 0.0 } }' # Get all channel configurations curl -X GET "http://energyme.local/api/v1/ade7953/channel" \ -H "Cookie: auth_token=YOUR_TOKEN" # Bulk update multiple channels curl -X PUT "http://energyme.local/api/v1/ade7953/channels" \ -H "Content-Type: application/json" \ -H "Cookie: auth_token=YOUR_TOKEN" \ -d '[ {"index": 0, "active": true, "label": "Main", "phase": 1, "ctSpecification": {"currentRating": 50.0, "voltageOutput": 0.333, "scalingFraction": 0.0}}, {"index": 1, "active": true, "label": "Kitchen", "phase": 1, "ctSpecification": {"currentRating": 30.0, "voltageOutput": 0.333, "scalingFraction": 0.0}} ]' ``` -------------------------------- ### Setup CSV Download Functionality Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/index.html Configures an event listener for a download button to generate and download consumption data as a CSV file. It dynamically creates the CSV content, including headers and data rows, based on the provided consumption data and view type (daily or monthly). ```javascript function setupCsvDownload(consumptionData, viewType, currentDate, currentMonth, channels, channelData, colors) { const downloadBtn = document.getElementById('download-csv'); downloadBtn.onclick = function() { const periods = Object.keys(consumptionData).sort(); const channelsSet = new Set(); periods.forEach(period => { Object.keys(consumptionData[period]).forEach(channel => { channelsSet.add(channel); }); }); const channelArray = [...channelsSet].sort((a, b) => { if (a === 'Other') return 1; if (b === 'Other') return -1; return parseInt(a) - parseInt(b); }); let csvContent = "data:text/csv;charset=utf-8,"; const periodLabel = viewType === 'daily' ? 'Hour' : 'Day'; csvContent += periodLabel + "," + channelArray.map(ch => getChannelLabel(ch, channels, channelData)).join(",") + "\n"; periods.forEach(period => { const periodDisplay = viewType === 'daily' ? period + ":00" : period; const row = [periodDisplay]; channelArray.forEach(channel => { row.push((consumptionData[period][channel] || 0).toFixed(3)); }); csvContent += row.join(",") + "\n"; }); const encodedUri = encodeURI(csvContent); const link = document.createElement("a"); const dateStr = viewType === 'daily' ? currentDate : currentMonth; const filename = `energy_consumption_${viewType}_${dateStr}.csv`; link.setAttribute("href", encodedUri); link.setAttribute("download", filename); document.body.appendChild(link); link.click(); document.body.removeChild(link); }; } ``` -------------------------------- ### REST API: Get System Information (Bash) Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Retrieves comprehensive system information from the EnergyMe-Home device. This includes static details like firmware version and chip model, as well as dynamic data such as memory usage, network status, and task monitoring. Requires an authentication token. ```bash # Get detailed system information curl -X GET "http://energyme.local/api/v1/system/info" \ -H "Cookie: auth_token=YOUR_TOKEN" # Response includes static and dynamic info: { "static": { "companyName": "EnergyMe", "productName": "Home", "buildVersion": "00.11.09", "chipModel": "ESP32-S3", "chipCores": 2, "flashChipSizeBytes": 16777216, "psramSizeBytes": 2097152 }, "dynamic": { "uptimeSeconds": 86400, "heapFreeBytes": 150000, "heapUsedPercentage": 45.2, "temperatureCelsius": 42.5, "wifiConnected": true, "wifiRssi": -55, "wifiLocalIp": "192.168.1.100" }, "safeMode": { "active": false, "canRestartNow": true } } ``` -------------------------------- ### Setup Event Listeners for UI Controls (JavaScript) Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/index.html Sets up event listeners for various UI elements, including view toggle buttons (daily, monthly, yearly) and date/month/year pickers. Changes in these controls trigger updates to the navigation buttons and reload/display charts. Dependencies include `switchView`, `loadAndDisplayCharts`, `updateNavigationButtons`. ```javascript function setupEventListeners() { // View toggle buttons document.getElementById('daily-view').addEventListener('click', () => { switchView('daily'); }); document.getElementById('monthly-view').addEventListener('click', () => { switchView('monthly'); }); document.getElementById('yearly-view').addEventListener('click', () => { switchView('yearly'); }); // Date picker change document.getElementById('date-picker').addEventListener('change', async (e) => { currentDate = e.target.value; updateNavigationButtons(); await loadAndDisplayCharts(); }); // Month picker change document.getElementById('month-picker').addEventListener('change', async (e) => { currentMonth = e.target.value; updateNavigationButtons(); await loadAndDisplayCharts(); }); // Year picker change document.getElementById('year-picker').addEventListener('change', async (e) => { currentYear = e.target.value; // The rest of the function is truncated in the input. ``` -------------------------------- ### Start Live Meter Updates Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/calibration.html Initiates a recurring process to fetch and update energy meter data at a defined interval. It clears any existing update intervals before starting a new one to prevent multiple fetches. Requires 'energyApi' to get meter values. ```javascript function startLiveMeterUpdates() { if (powerUpdateInterval) { clearInterval(powerUpdateInterval); } const updateMeterData = async () => { try { const meterValuesArray = await energyApi.getMeterValues(); meterData = meterValuesArray; updateMeterTable(); } catch (error) { console.error('Error fetching meter data:', error); } }; updateMeterData(); powerUpdateInterval = setInterval(updateMeterData, FETCH_THROTTLE); } ``` -------------------------------- ### Download File from Filesystem Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Downloads a specific file from the LittleFS filesystem. Requires authentication and saves the file to the specified output path. ```bash curl -X GET "http://energyme.local/api/v1/files/energy/daily/2025-01-14.csv.gz?download=true" \ -H "Cookie: auth_token=YOUR_TOKEN" \ -o energy-data.csv.gz ``` -------------------------------- ### Log Levels API Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Endpoints for getting and setting the log levels for the EnergyMe Home device. ```APIDOC ## GET /api/v1/logs/level ### Description Retrieves the current log levels for print and save operations. ### Method GET ### Endpoint /api/v1/logs/level ### Parameters #### Query Parameters None #### Request Body None ### Request Example ```bash curl -X GET "http://energyme.local/api/v1/logs/level" \ -H "Cookie: auth_token=YOUR_TOKEN" ``` ### Response #### Success Response (200) - **print** (string) - The current log level for printing. - **save** (string) - The current log level for saving. #### Response Example ```json { "print": "INFO", "save": "WARNING" } ``` ## PATCH /api/v1/logs/level ### Description Sets the log levels for print and save operations. ### Method PATCH ### Endpoint /api/v1/logs/level ### Parameters #### Query Parameters None #### Request Body - **print** (string) - The desired log level for printing (e.g., "DEBUG", "INFO", "WARNING", "ERROR"). - **save** (string) - The desired log level for saving (e.g., "DEBUG", "INFO", "WARNING", "ERROR"). ### Request Example ```bash curl -X PATCH "http://energyme.local/api/v1/logs/level" \ -H "Content-Type: application/json" \ -H "Cookie: auth_token=YOUR_TOKEN" \ -d '{"print": "DEBUG", "save": "WARNING"}' ``` ### Response #### Success Response (200) Indicates successful update of log levels. Response body may be empty or confirm the new settings. #### Response Example ```json { "message": "Log levels updated successfully." } ``` ``` -------------------------------- ### Initialize and Update System Info (JavaScript) Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/info.html This code snippet sets up the initial loading of system information when the DOM is fully loaded and establishes a recurring interval to fetch and update this information every 5 seconds. It relies on a `fetchSystemInfo` function, which is not provided in this snippet but is assumed to handle the actual data retrieval and DOM updates. ```javascript document.addEventListener('DOMContentLoaded', function() { fetchSystemInfo(); setInterval(fetchSystemInfo, 5000); // Update every 5 seconds }); ``` -------------------------------- ### Initialize Page and Load Energy Data (JavaScript) Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/index.html Initializes the web page by fetching channel configuration and meter data, updating real-time displays, loading available dates from various archives, and setting up the date picker. It also handles error scenarios and displays appropriate messages. Dependencies include `energyApi`, `decompressGzipFile`, `loadAvailableDates`, `updateMeterData`, `updateNavigationButtons`, `loadAndDisplayCharts`, `updateTotalPieChart`, `showNoDataMessage`, `setupEventListeners`, `showErrorMessage`. ```javascript async function initializePage() { try { // Get channel configuration and current meter data [channelData, meterData] = await Promise.all([ energyApi.getChannelConfig(), energyApi.getMeterValues() ]); // Update real-time displays updateMeterData(); // Get available energy files await loadAvailableDates(); // Set up date picker with most recent date if (availableDates.length > 0) { currentDate = availableDates[availableDates.length - 1]; currentMonth = availableMonths[availableMonths.length - 1]; currentYear = availableYears[availableYears.length - 1]; document.getElementById('date-picker').value = currentDate; document.getElementById('month-picker').value = currentMonth; document.getElementById('year-picker').value = currentYear; updateNavigationButtons(); await loadAndDisplayCharts(); await updateTotalPieChart(); } else { showNoDataMessage(); } // Set up event listeners setupEventListeners(); } catch (error) { console.error('Error initializing page:', error); showErrorMessage('Failed to load energy data'); } } ``` -------------------------------- ### List Files in Filesystem Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Lists all files in the LittleFS filesystem, optionally filtered by a folder. Requires authentication and returns a JSON object mapping filenames to their sizes. ```bash curl -X GET "http://energyme.local/api/v1/list-files" \ -H "Cookie: auth_token=YOUR_TOKEN" ``` ```bash curl -X GET "http://energyme.local/api/v1/list-files?folder=energy/daily" \ -H "Cookie: auth_token=YOUR_TOKEN" ``` -------------------------------- ### Load Configuration Data Sequentially (JavaScript) Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/configuration.html This JavaScript function loads various configuration settings sequentially with delays to prevent overwhelming the ESP32. It includes error handling and logs the process. Dependencies include `getCloudServices`, `getLedBrightness`, `getLogLevel`, `getCustomMqttConfiguration`, `getInfluxDbConfiguration`, `checkHasSecrets`, and `loadChannelData`. ```javascript sync function loadConfigurationData() { const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); const DELAY_BETWEEN_REQUESTS = 100; try { console.log("Loading configuration data sequentially..."); await getCloudServices(); await delay(DELAY_BETWEEN_REQUESTS); await getLedBrightness(); await delay(DELAY_BETWEEN_REQUESTS); await getLogLevel(); await delay(DELAY_BETWEEN_REQUESTS); await getCustomMqttConfiguration(); await delay(DELAY_BETWEEN_REQUESTS); await getInfluxDbConfiguration(); await delay(DELAY_BETWEEN_REQUESTS); await checkHasSecrets(); await delay(DELAY_BETWEEN_REQUESTS); await loadChannelData(); console.log("Configuration data loaded successfully"); } catch (error) { console.error("Error loading configuration data:", error); alert("Error loading configuration data. Please refresh the page."); } } ``` -------------------------------- ### Upload Firmware for OTA Update Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Uploads new firmware for over-the-air updates with MD5 verification. Requires authentication and the firmware file, along with the MD5 hash in the header. ```bash curl -X POST "http://energyme.local/api/v1/ota/upload" \ -H "X-MD5: a1b2c3d4e5f6789012345678abcdef12" \ -H "Cookie: auth_token=YOUR_TOKEN" \ -F "firmware=@firmware.bin" ``` -------------------------------- ### Get InfluxDB Configuration (JavaScript) Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/configuration.html Retrieves the current InfluxDB configuration from the energy API and populates the corresponding form fields in the UI. This allows users to view and modify their existing InfluxDB settings. ```javascript function getInfluxDbConfiguration() { energyApi.getInfluxDbConfig() .then(data => { influxDbConfig = data; document.getElementById("influxDbEnabled").checked = influxDbConfig.enabled; document.getElementById("influxDbServer").value = influxDbConfig.server; document.getElementById("influxDbPort").value = influxDbConfig.port; document.getElementById("influxDbVersion").value = influxDbConfig.version; document.getElementById("influxDbDatabase").value = influxDbConfig.database; document.getElementById("influxDbUsername").value = influxDbConfig.username; document.getElementById("influxDbPassword") ``` -------------------------------- ### Get Cloud Services Status (JavaScript) Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/configuration.html Fetches the current status (enabled/disabled) of cloud services from the energy API and updates a checkbox element in the UI. Includes error handling for the API request. ```javascript function getCloudServices() { energyApi.getMqttCloudServices() .then(data => { document.getElementById("cloudServices").checked = data.enabled; }) .catch(error => { console.log("Error getting cloud services status. Response: " + error.message); }); } ``` -------------------------------- ### Channel Configuration API Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Configure monitoring parameters for specific circuit channels, including labels, phase assignments, CT specifications, and active/reverse status. Supports partial updates, getting all configurations, and bulk updates. ```APIDOC ## Channel Configuration API ### Description Configure monitoring parameters for a specific circuit channel including label, phase assignment, CT specifications, and active/reverse status. Supports partial updates, retrieving all channel configurations, and bulk updates for multiple channels. ### Method PATCH, GET, PUT ### Endpoint - `/api/v1/ade7953/channel` (for single channel PATCH/GET) - `/api/v1/ade7953/channels` (for bulk PUT) ### Parameters #### Path Parameters None #### Query Parameters - **index** (integer) - Required for GET requests to retrieve a specific channel's configuration. Optional for GET requests to retrieve all configurations. #### Request Body ##### PATCH `/api/v1/ade7953/channel` - **index** (integer) - Required - The index of the channel to configure. - **active** (boolean) - Optional - Whether the channel is active. - **reverse** (boolean) - Optional - Whether the channel is in reverse mode. - **highPriority** (boolean) - Optional - Whether the channel has high priority. - **label** (string) - Optional - A custom label for the channel. - **phase** (integer) - Optional - The phase assignment for the channel. - **ctSpecification** (object) - Optional - Specifications for the Current Transformer. - **currentRating** (float) - The current rating of the CT. - **voltageOutput** (float) - The voltage output of the CT. - **scalingFraction** (float) - The scaling fraction for the CT. ##### PUT `/api/v1/ade7953/channels` - An array of channel objects, each with an `index` and other configurable fields. ### Request Example ```bash # Update channel configuration (partial update) curl -X PATCH "http://energyme.local/api/v1/ade7953/channel" \ -H "Content-Type: application/json" \ -H "Cookie: auth_token=YOUR_TOKEN" \ -d '{ "index": 1, "active": true, "reverse": false, "highPriority": true, "label": "Kitchen Circuit", "phase": 1, "ctSpecification": { "currentRating": 30.0, "voltageOutput": 0.333, "scalingFraction": 0.0 } }' # Get all channel configurations curl -X GET "http://energyme.local/api/v1/ade7953/channel" \ -H "Cookie: auth_token=YOUR_TOKEN" # Bulk update multiple channels curl -X PUT "http://energyme.local/api/v1/ade7953/channels" \ -H "Content-Type: application/json" \ -H "Cookie: auth_token=YOUR_TOKEN" \ -d '[ {"index": 0, "active": true, "label": "Main", "phase": 1, "ctSpecification": {"currentRating": 50.0, "voltageOutput": 0.333, "scalingFraction": 0.0}}, {"index": 1, "active": true, "label": "Kitchen", "phase": 1, "ctSpecification": {"currentRating": 30.0, "voltageOutput": 0.333, "scalingFraction": 0.0}} ]' ``` ### Response #### Success Response (200) - For PATCH/PUT: Returns the updated channel configuration(s). - For GET (all channels): Returns an array of channel configuration objects. - For GET (specific channel): Returns the configuration object for the specified channel. Each channel configuration object includes: - **index** (integer) - **active** (boolean) - **reverse** (boolean) - **highPriority** (boolean) - **label** (string) - **phase** (integer) - **ctSpecification** (object) - **currentRating** (float) - **voltageOutput** (float) - **scalingFraction** (float) #### Response Example ```json # Example response for GET /api/v1/ade7953/channel?index=1 { "index": 1, "active": true, "reverse": false, "highPriority": true, "label": "Kitchen Circuit", "phase": 1, "ctSpecification": { "currentRating": 30.0, "voltageOutput": 0.333, "scalingFraction": 0.0 } } ``` ``` -------------------------------- ### REST API: Get Meter Values (Bash) Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Fetches real-time energy measurements from the ADE7953 IC on the EnergyMe-Home device. It can retrieve data for all active channels or a specific channel by its index. Requires an authentication token. ```bash # Get meter values for all active channels curl -X GET "http://energyme.local/api/v1/ade7953/meter-values" \ -H "Cookie: auth_token=YOUR_TOKEN" # Get meter values for specific channel (0-16) curl -X GET "http://energyme.local/api/v1/ade7953/meter-values?index=0" \ -H "Cookie: auth_token=YOUR_TOKEN" # Response for single channel: { "voltage": 230.2, "current": 5.45, "activePower": 1254.6, "reactivePower": 45.2, "apparentPower": 1256.4, "powerFactor": 0.998, "activeEnergyImported": 12345.6, "activeEnergyExported": 0.0, "reactiveEnergyImported": 234.5, "reactiveEnergyExported": 0.0, "apparentEnergy": 12346.8 } # Response for all channels: { "channels": [ { "voltage": 230.2, "current": 5.45, "activePower": 1254.6, ... }, { "voltage": 230.1, "current": 2.10, "activePower": 483.2, ... } ] } ``` -------------------------------- ### Synchronize Device Time (JavaScript) Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/configuration.html Initiates the time synchronization process with the device. It gets the current Unix timestamp, sends it to the energy API, and updates the UI with the result. Includes user confirmation and error handling. ```javascript function syncTime() { const syncButton = document.getElementById("syncTime"); syncButton.innerHTML = "Syncing..."; syncButton.disabled = true; const unixSeconds = Math.floor(Date.now() / 1000); energyApi.setSystemTime(unixSeconds) .then(response => { syncButton.innerHTML = "🕐 Sync Time"; syncButton.disabled = false; alert("Time synchronized successfully! New time: " + response.newTime); loadDeviceTime(); }) .catch(error => { syncButton.innerHTML = "🕐 Sync Time"; syncButton.disabled = false; alert("Error syncing time: " + error.message); }); } // Load device time on page load document.addEventListener("DOMContentLoaded", function() { loadDeviceTime(); }); ``` -------------------------------- ### Start Global Power Updates (JavaScript) Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/channel.html Manages the interval for fetching and updating power values for all active channels. It ensures only one interval is running and periodically calls a function to update power readings from the API. ```javascript function startGlobalPowerUpdates() { // Stop any existing interval if (powerUpdateInterval) { clearInterval(powerUpdateInterval); } const updateAllPowerValues = async () => { try { const meterValuesArray = await energyApi.getMeterValues(); // Update only active channels meterValuesArray.forEach(channelMeterData => { const index = channelMeterData.index; const powerElement = document.getElementById(`power${index}`); // Only show power if channel is active if (powerElement && channelData[index] && channelData[index].active && channel ``` -------------------------------- ### Fetch Firmware Update Info (JavaScript) Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/index.html Fetches firmware update information from the energy API. If the latest firmware is not installed, it appends a notification emoji to a specific navigation element. Includes error handling for API requests. ```javascript async function fetchFirmwareUpdateInfo() { try { const data = await energyApi.getFirmwareUpdateInfo(); if (data.latest == false) { document.querySelector('.buttonNavigation[href="/update"]').innerHTML += ' 🔔'; } } catch (error) { console.error('Error fetching firmware update info:', error); } } ``` -------------------------------- ### Initialize Page and Load Channel Configuration (JavaScript) Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/channel.html Initializes the page by fetching channel configuration from the energy API and creating visual representations of each channel. It handles loading states and errors during initialization. ```javascript var channelData = {}; var powerUpdateInterval = null; const FETCH_THROTTLE = 2000; // Increased for better stability var updateQueue = {}; var isProcessingUpdate = false; // Initialize the page async function initializePage() { try { document.getElementById('updateStatus').textContent = 'Loading...'; // Load channel config only const channelResponse = await energyApi.getChannelConfig(); channelData = channelResponse; createChannelBoxes(); document.getElementById('updateStatus').textContent = ''; } catch (error) { console.error('Error initializing page:', error); document.getElementById('updateStatus').textContent = 'Error loading data: ' + error.message; } } // Initialize when page loads document.addEventListener('DOMContentLoaded', initializePage); ``` -------------------------------- ### Filter CSV Data by Date Prefix Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/index.html A helper function to filter CSV text content, returning only the lines that start with a specified date prefix. It preserves the header row. Returns null if no matching lines are found. ```javascript function filterCsvByDate(csvText, datePrefix) { const lines = csvText.trim().split('\n'); const header = lines[0]; const dataLines = lines.slice(1).filter(line => line.startsWith(datePrefix)); if (dataLines.length === 0) return null; return header + '\n' + dataLines.join('\n'); } ``` -------------------------------- ### Load Energy Channel Data and Create Inputs (JavaScript) Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/configuration.html Fetches channel configuration data from the API, stores it, and then creates corresponding input fields in the UI. It includes a small delay before loading energy values to prevent overwhelming the ESP32 device. ```javascript function loadChannelData() { return energyApi.getChannelConfig() .then(data => { channelData = data; createEnergyChannelInputs(); // Add a delay before loading energy values to prevent overwhelming ESP32 return new Promise(resolve => setTimeout(resolve, 300)); }) .then(() => { return loadEnergyValues(); }) .catch(error => { console.log("Error getting channel data. Response: " + error.message); throw error; // Re-throw to handle in calling function }); } function createEnergyChannelInputs() { const container = document.getElementById("energyChannels"); container.innerHTML = ""; for (let channelIndex in channelData) { const channel = channelData[channelIndex]; if (channel.active) { const channelDiv = document.createElement("div"); channelDiv.style.cssText = ` margin-bottom: 24px; border: 1px solid #e1e5e9; border-radius: 12px; background: linear-grad ``` -------------------------------- ### MCP Server Integration Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Instructions for setting up and integrating with the MCP (Model Context Protocol) server for AI assistant integration. ```APIDOC ## MCP Server Integration ### Description This section details how to install, run, and configure the MCP server for AI assistant integration with EnergyMe Home. ### Installation and Running 1. Navigate to the MCP server directory: ```bash cd mcp-server ``` 2. Install the MCP server package: ```bash pip install -e . ``` 3. Run the MCP server: ```bash python server.py ``` ### Environment Variables Configure the following environment variables before running the server or client: - `ENERGYME_BASE_URL`: The base URL of your EnergyMe Home device (e.g., `http://192.168.1.100`). - `ENERGYME_USERNAME`: The username for accessing the EnergyMe device. - `ENERGYME_PASSWORD`: The password for accessing the EnergyMe device. Example configuration: ```bash export ENERGYME_BASE_URL="http://192.168.1.100" export ENERGYME_USERNAME="admin" export ENERGYME_PASSWORD="energyme" ``` ### Testing with MCP Inspector Use the MCP inspector to test the server connection: ```bash npx @modelcontextprotocol/inspector uv --directory . run server.py ``` ### VS Code / Claude Desktop MCP Configuration To configure your IDE for MCP integration, add the following to your `settings.json` (or equivalent): ```json { "servers": { "EnergyMe Home": { "type": "stdio", "command": "uv", "args": ["--directory", "/path/to/EnergyMe-Home/mcp-server", "run", "server.py"], "env": { "ENERGYME_BASE_URL": "http://192.168.1.100", "ENERGYME_USERNAME": "admin", "ENERGYME_PASSWORD": "your_password" } } } } ``` Replace `/path/to/EnergyMe-Home/mcp-server` with the actual path to your `mcp-server` directory and update credentials as needed. ``` -------------------------------- ### Get Crash Information via API Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Shows how to retrieve crash information from the EnergyMe Home device using its REST API. This includes details like the reset reason, crash count, and backtrace information. Requires an authentication token. ```bash curl -X GET "http://energyme.local/api/v1/crash/info" \ -H "Cookie: auth_token=YOUR_TOKEN" ``` -------------------------------- ### Filter CSV Data by Month Prefix Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/index.html A helper function to filter CSV text content, returning only the lines that start with a specified month prefix (YYYY-MM). It preserves the header row. Returns null if no matching lines are found. ```javascript function filterCsvByMonth(csvText, monthPrefix) { const lines = csvText.trim().split('\n'); const header = lines[0]; const dataLines = lines.slice(1).filter(line => line.startsWith(monthPrefix)); if (dataLines.length == 0) return null; return header + '\n' + dataLines.join('\n'); } ``` -------------------------------- ### VS Code / Claude Desktop MCP Configuration Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Configuration snippet for integrating the EnergyMe Home project with VS Code or Claude Desktop using the MCP protocol. It specifies server connection details and environment variables. ```json { "servers": { "EnergyMe Home": { "type": "stdio", "command": "uv", "args": ["--directory", "/path/to/EnergyMe-Home/mcp-server", "run", "server.py"], "env": { "ENERGYME_BASE_URL": "http://192.168.1.100", "ENERGYME_USERNAME": "admin", "ENERGYME_PASSWORD": "your_password" } } } } ``` -------------------------------- ### Restart System Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Restarts the EnergyMe Home device. Requires authentication. ```bash curl -X POST "http://energyme.local/api/v1/system/restart" \ -H "Cookie: auth_token=YOUR_TOKEN" ``` -------------------------------- ### Manage Global Power Updates - JavaScript Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/channel.html Controls the interval for fetching and updating power values across all active channels. It provides functions to start and stop this global update mechanism, ensuring power data is refreshed periodically. ```javascript function startGlobalPowerUpdates() { if (!powerUpdateInterval) { powerUpdateInterval = setInterval(updateAllPowerValues, FETCH_THROTTLE); } } function stopGlobalPowerUpdates() { if (powerUpdateInterval) { clearInterval(powerUpdateInterval); powerUpdateInterval = null; } } ``` -------------------------------- ### Read Energy Measurements via Modbus TCP (Python) Source: https://context7.com/jibrilsharafi/energyme-home/llms.txt Python example using the pymodbus library to connect to the EnergyMe device via Modbus TCP and read voltage measurements. It demonstrates connecting, reading registers, and handling potential errors. ```python from pymodbus.client import ModbusTcpClient client = ModbusTcpClient('192.168.1.100', port=502) client.connect() # Read voltage register (example register address) result = client.read_holding_registers(address=0, count=2, unit=1) if not result.isError(): voltage = result.registers[0] / 100.0 # Scale factor depends on register print(f"Voltage: {voltage} V") client.close() ``` -------------------------------- ### Initialize Swagger UI Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/swagger.html JavaScript code to initialize the Swagger UI. It loads the OpenAPI specification from '/swagger.yaml' and configures various UI options such as deep linking and extension display. ```javascript window.onload = function () { const ui = SwaggerUIBundle({ url: "/swagger.yaml", dom_id: '#swagger-ui', presets: [ SwaggerUIBundle.presets.apis, SwaggerUIBundle.SwaggerUIStandalonePreset ], layout: "BaseLayout", deepLinking: true, showExtensions: true, showCommonExtensions: true }); } ``` -------------------------------- ### Initialize and Update Live Meter Data (JavaScript) Source: https://github.com/jibrilsharafi/energyme-home/blob/main/source/html/calibration.html Initializes the page by fetching channel configurations and starting live meter updates. It handles loading states and errors during initialization. Updates are fetched periodically, with throttling to manage API calls. ```javascript var channelData = {}; var meterData = []; var selectedChannelIndex = null; var powerUpdateInterval = null; var scalingPercentage = 0; // Store as percentage const FETCH_THROTTLE = 2000; // Initialize the page async function initializePage() { try { document.getElementById('updateStatus').textContent = 'Loading...'; const channelResponse = await energyApi.getChannelConfig(); channelData = channelResponse; populateChannelDropdown(); startLiveMeterUpdates(); document.getElementById('updateStatus').textContent = ''; } catch (error) { console.error('Error initializing page:', error); document.getElementById('updateStatus').textContent = 'Error loading data: ' + error.message; } } function populateChannelDropdown() { const dropdown = document.getElementById('channelSelect'); dropdown.innerHTML = ''; Object.entries(channelData).forEach(([index, channel]) => { if (channel.active) { const option = document.createElement('option'); option.value = index; option.textContent = `Channel ${index}: ${channel.label}`; dropdown.appendChild(option); } }); } function startLiveMeterUpdates() { if (powerUpdateInterval) clearInterval(powerUpdateInterval); powerUpdateInterval = setInterval(async () => { if (!selectedChannelIndex) return; try { const data = await energyApi.getMeterData(selectedChannelIndex); meterData = data; updateMeterDisplay(data); } catch (error) { console.error('Error fetching meter data:', error); document.getElementById('updateStatus').textContent = 'Error updating meter data: ' + error.message; } }, FETCH_THROTTLE); } function updateMeterDisplay(data) { // Placeholder for updating the UI with meter data console.log('Meter Data:', data); // Example: document.getElementById('voltageDisplay').textContent = data.voltage + ' V'; } ```