# Product

Book on product development. Metering, Microgrid OS, Batteries, Invertors, Solar panels

# Capability Evaluation Criteria

<table border="1" id="bkmrk-attribute%C2%A0-cost-inte" style="border-collapse: collapse; width: 100%; height: 106.2px;"><colgroup><col style="width: 16.6667%;"></col><col style="width: 16.6667%;"></col><col style="width: 16.6667%;"></col><col style="width: 16.6667%;"></col><col style="width: 16.6667%;"></col><col style="width: 16.6667%;"></col></colgroup><tbody><tr style="height: 46.6px;"><td style="height: 46.6px;">**Attribute**   
</td><td style="height: 46.6px;">**Cost**</td><td style="height: 46.6px;">**Interoperability**   
</td><td style="height: 46.6px;">**Long term relationship**</td><td style="height: 46.6px;">**Deployment readiness**</td><td style="height: 46.6px;">**Build Quality**</td></tr><tr style="height: 29.8px;"><td style="height: 29.8px;">1</td><td style="height: 29.8px;">over market price</td><td style="height: 29.8px;">proprietary standards, risk of vendor lock-in</td><td style="height: 29.8px;">cannot reliably communicate, needs aggressive follow up and management   
</td><td style="height: 29.8px;">timeline unclear or unknown   
</td><td style="height: 29.8px;">Questionable may need replacement anytime or unknown durability   
</td></tr><tr><td>3</td><td>close to or exactly at market price</td><td>use some open and proprietary standards   
</td><td>can communicate reliably but needs incentives to do so   
</td><td>timeline is known but is volatile or longer than what is needed   
</td><td>Acceptable could last 2 to 3 years   
</td></tr><tr style="height: 29.8px;"><td style="height: 29.8px;">5</td><td style="height: 29.8px;">under market price</td><td style="height: 29.8px;">fully using open standards</td><td style="height: 29.8px;">communicates reliably and incentives are already aligned   
</td><td style="height: 29.8px;">timeline is known and predictable or within acceptable duration</td><td style="height: 29.8px;">Durable can last 3 years or more   
</td></tr></tbody></table>

# Microgrid OS

Monitoring and Steering assets on the microgrid

# Microgrid OS Evaluation

<table border="1" id="bkmrk-attribute-cost-%28mone" style="border-collapse: collapse; width: 106.786%; height: 305.578px;"><colgroup><col style="width: 19.0703%;"></col><col style="width: 13.5876%;"></col><col style="width: 14.4219%;"></col><col style="width: 15.1371%;"></col><col style="width: 12.519%;"></col><col style="width: 13.7027%;"></col><col style="width: 11.6806%;"></col></colgroup><tbody><tr style="height: 46.5938px;"><td style="height: 46.5938px;">OS</td><td style="height: 46.5938px;">Cost (money)</td><td style="height: 46.5938px;">Interoperability</td><td style="height: 46.5938px;">long term relationship</td><td style="height: 46.5938px;">Deployment Readiness</td><td style="height: 46.5938px;">Quality   
</td><td style="height: 46.5938px;">Features</td></tr><tr style="height: 46.5938px;"><td style="height: 46.5938px;">[NewSunRoad Stellar](https://newsunroad.com/stellar-microgrid-os/)</td><td style="height: 46.5938px;">  
</td><td style="height: 46.5938px;">  
</td><td style="height: 46.5938px;">  
</td><td style="height: 46.5938px;">  
</td><td style="height: 46.5938px;">  
</td><td style="height: 46.5938px;">  
</td></tr><tr style="height: 35.3984px;"><td style="height: 35.3984px;">[Remot by Innovex](https://innovex.org/remot/)</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td></tr><tr style="height: 35.3984px;"><td style="height: 35.3984px;">[Inhemeter](https://www.inhemeter.com/en/Default.aspx)   
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td></tr><tr style="height: 35.3984px;"><td style="height: 35.3984px;">[GxF by LF Energy](https://www.inhemeter.com/en/Default.aspx "GxF Platform Evaluation")</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td></tr><tr style="height: 35.3984px;"><td style="height: 35.3984px;">[MicroPower Manager](https://micropowermanager.io/get-started.html)</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td></tr><tr style="height: 35.3984px;"><td style="height: 35.3984px;">[Hyphae by LF Energy](https://lfenergy.org/projects/hyphae/)</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td></tr><tr style="height: 35.3984px;"><td style="height: 35.3984px;">[OpenEMS](https://openems.io/)</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td><td style="height: 35.3984px;">  
</td></tr><tr><td>[Sunalyzer](https://github.com/BorisBrock/Sunalyzer)</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td></tr></tbody></table>

### New Sun Road Stellar 

Stellar seems to have all the capabilities we want from their website but Michael (CTO) confirms that he is not sure that the meters are are using are supported 100%. They can likely monitor usage data but may not be able to remote on/off. It is proprietary.

### Remot by Innovex

The Innovex team has not been responsive to our email requests for more information about this. Also, their website seems to be frequently down.

### Inhemeter

We were not about to get a demo or even an order for meters out of this company. Their meters are known to be good quality but I think they are not interested in working with us because we are a small new company.

### GxF by LF energy 

This project is actually a macrogrid OS that currently still being open sourced. A number of key components like the GUI for smart metering is not yet open sourced. It is worth watching because it has potential to run for a microgrid because it has smart metering and public lighting capabilities.

### MicroPowerManager 

This is one looks very promising. Open source and field tested. I think it's ripe for us to take to production and prove it out. It also has an associated battery management capability which makes this community seem like a good fit for NFE.

### Hyphae by LF Energy

I think Hyphae has a bold vision for an autonomous microgrid. It currently only has peer to peer battery power interchange capabilities and no metering. Also not get field tested but has some simulation capabilities.

# GxF Platform Evaluation

### Overview

GxF is an opensource platform (set of capabilities; metering, public lighting) for distribution of power on a grid. It is currently being used by and was donated to the open source community by a Dutch utility company called Alliander.

### Links

Here's some useful links from my discovery work on GxF

- [Understanding it's capabilities](https://chatgpt.com/share/68265830-00b0-800c-9289-d26d1f3a5a4d)
- [Official docs](https://lfenergy.org/projects/gxf/)
- [Video Overview](https://www.youtube.com/watch?v=zqEPa9Lpq58&list=PLKyFf1J9XkpvpkbiptMX9XDmDnjc5R71d)
- [GxF on M1 Mac](https://chatgpt.com/share/68265959-1b18-800c-8940-c35290087a59)
- [Microgrid Management Software ](https://chatgpt.com/share/676e8ad0-d7e8-800c-b590-dde15a0eba7d)

### Next Steps   


Continue deployment to digital ocean VM

- Start by reviewing all [these packages](https://github.com/orgs/OSGP/packages?repo_name=open-smart-grid-platform) and understanding which ones you want to deploy or explore whether it makes more sense to rebuild the latest release and deploy packages from that.
- To run the GXF (Grid eXchange Fabric) platform, you generally need only a subset of the packages published in the OSGP GitHub organization—specifically, those that are direct dependencies for the platform's core services and adapters.
- GXF is a modular system, and the required packages depend on your deployment goals. Commonly, the following package types are used:
- Core Platform Packages – These include the main server components, messaging infrastructure, shared libraries, and authentication modules. 
    - Protocol Adapters – Depending on your use case, you’ll need the adapters that communicate with your field devices (e.g., OSLP, DLMS, IEC61850).
    - Domain and WS Adapters – These provide domain-specific logic and web service endpoints (e.g., smart metering, microgrids, public lighting).
    - Shared Utilities – Supporting packages shared between multiple modules.

 Steps to Determine Required Packages

- Review the GXF Deployment Documentation: The official \[GXF deployment guide\](https://github.com/OSGP/open-smart-grid-platformdocumentation) lists the core components and adapters you need to deploy for a standard platform.
- Match Packages to Components: Identify which packages correspond to those components (e.g., "osgp-adapter-domain-smart-metering", "osgp-adapter-ws-publiclighting", etc.).

Focus on Smart metering Use Case: One of the maintainers tells t<span lang="en-us" style="max-width: 100%;" xml:lang="en-us">he application’s current design allows you to deploy only the smart metering components, along with some core GxF components. You’ll need the following components for smart metering:</span>

- <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">core GxF components:</span>
    - <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">osgp-adapter-domain-admin</span>
    - <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">osgp-adapter-domain-core</span>
    - <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">osgp-adapter-ws-admin</span>
    - <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">osgp-adapter-ws-core</span>
    - <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">osgp-core</span>
    - <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">osgp-logging</span>
- <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">Smart metering specific components</span>
    - <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">osgp-adapter-domain-smartmetering</span>
    - <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">osgp-adapter-ws-smartmetering</span>
    - <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">osgp-protocol-adapter-dlms</span>
    - <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">osgp-throttling-service</span>
    - <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">osgp-secret-management</span>
- <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">Smart metering simulator</span>
    - <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">osgp-simulator-dlms-triggered</span>
    - <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">dlms-device-simulator-starter</span>

<span lang="en-us" style="max-width: 100%;" xml:lang="en-us">These components do not contain any user interface but provide a SOAP interface for communication with the GxF platform. The user interface is currently not part of the open-source implementation.</span>

- <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">We could set up RESTful APIs and build a GUI we can use and contribute back to the community or we can also try to build a UI from the SOAP API available. Open to either, I don't know how much we can do with API only if we don't have a GUI.   
    </span>

### <span lang="en-us" style="max-width: 100%;" xml:lang="en-us">Historical Context   
</span>

From Sander (Maintainer). I recommend you join the [project mailing list](https://lists.lfenergy.org/g/gxf), introduce yourself (I already did) and use it to ask questions along the way.. I have found it very useful and Sander is very helpful in responding there.

> We are currently in the process of creating an open-source containerized solution for deploying and testing GxF. With this solution it will be possible to run GxF locally in k3d - a lightweight wrapper to run k3s (a minimal Kubernetes distribution) in docker - and to run automated tests using cucumber. For this you will need at least 32 GB of RAM, 64 GB is preferable. The solution can be found here: [https://github.com/OSGP/gxf-gitops](https://github.com/OSGP/gxf-gitops). Container images can be found in [ https://github.com/orgs/OSGP/packages?repo\_name=open-smart-grid-platform](https://github.com/orgs/OSGP/packages?repo_name=open-smart-grid-platform). Currently the gxf-gitops repository only contains the charts to deploy and test our flexible public lighting solution. The deployment of our smart metering solution is still work in progress.
> 
> As a side note, I would like to mention that the current smart metering implementation is specifically tailored to the Dutch market, so it would probably need several changes to make it operable outside of the Netherlands.
> 
> In the past we also used to have a distinct microgrids solution available, but as it was no longer used, we removed it from our codebase. However, the old microgrids components can still be found in the GitHub history:
> 
> - [https://github.com/OSGP/open-smart-grid-platform/tree/release-5.28.0/osgp/platform/osgp-adapter-domain-microgrids](https://github.com/OSGP/open-smart-grid-platform/tree/release-5.28.0/osgp/platform/osgp-adapter-domain-microgrids)
> - [https://github.com/OSGP/open-smart-grid-platform/tree/release-5.28.0/osgp/platform/osgp-adapter-ws-microgrids](https://github.com/OSGP/open-smart-grid-platform/tree/release-5.28.0/osgp/platform/osgp-adapter-ws-microgrids)
> - [https://github.com/OSGP/open-smart-grid-platform/tree/release-5.28.0/osgp/protocol-adapter-iec61850](https://github.com/OSGP/open-smart-grid-platform/tree/release-5.28.0/osgp/protocol-adapter-iec61850)
> - [https://github.com/OSGP/open-smart-grid-platform/tree/release-5.28.0/integration-tests/cucumber-tests-platform-microgrids](https://github.com/OSGP/open-smart-grid-platform/tree/release-5.28.0/integration-tests/cucumber-tests-platform-microgrids)
> 
> but they will require some serious dusting off to make them usable again.

# Microgrid Design with OpenSolar

<p class="callout success">We have an OpenSolar NFE account, reach out to <aaron.tushabe@nearlyfreeenergy.com> for an invite. </p>

⚙️ [**View and Bookmark all Training &amp; Support Links**](https://calendly.com/url?q=https%3A%2F%2Fsupport.opensolar.com%2Fhc%2Fen-us%2Farticles%2F7561221287951&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=69621de3e44d0b7a03913c9b725eed81f347a447c59942cd83e97f48515b01ec)

**Webinar Recordings**

🎥 [Design Training](https://calendly.com/url?q=https%3A%2F%2Fsupport.opensolar.com%2Fhc%2Fen-us%2Farticles%2F7576156328207%3F&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=ee0ebb2e5e0b6a101930c3c2f7df2384534319635e9296c6e01975512124290d)

🎥 [Account Setup](https://calendly.com/url?q=https%3A%2F%2Fsupport.opensolar.com%2Fhc%2Fen-us%2Farticles%2F7561437393551%3F&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=d5789103ec4ba420229d9c02486b30cdaa9601f130bde05258960163735120c5)

🎥 [MCS](https://calendly.com/url?q=https%3A%2F%2Fsupport.opensolar.com%2Fhc%2Fen-us%2Farticles%2F8582194074511%3F&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=afbdbd3ae73c9fd92147b7bec938b8db8575d848389b1d733cf60f89e37b5184)

🎥 [Battery Control Schemes](https://calendly.com/url?q=https%3A%2F%2Fsupport.opensolar.com%2Fhc%2Fen-us%2Farticles%2F8346227448463%3F&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=9809560c2567f6699f11991fcab0936cd6526f80b61c58c6f554ee92a596e136)

**Webinars**

☀️ [Weekly Training Sessions](https://calendly.com/url?q=https%3A%2F%2Fwww.opensolar.com%2Fwebinars-uk&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=8f14c921c6a7e01774c69e6f909366503046265a105c7e9cd436a0af5fc95769)

*View availability and book our dedicated UK training sessions.*

**Purchasing &amp; Supplier Integrations**

🎥 [Segen](https://calendly.com/url?q=https%3A%2F%2Fsupport.opensolar.com%2Fhc%2Fen-us%2Farticles%2F8216114678671-Segen-Hardware-Ordering-UK&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=e8458d633d7f9246dc027b32e718ef3b82f2b8b7b0cf3c800373bf835452707e)

🎥 [City Plumbing](https://calendly.com/url?q=https%3A%2F%2Fsupport.opensolar.com%2Fhc%2Fen-us%2Farticles%2F9435203134095-City-Plumbing-Hardware-Ordering-UK%3F&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=6f7a2a8dcf912a942ba7e2e4cce2b9b209109e01b9e02a5cc9a2c87e248e7067)

**Support**

☀️ [AI Chatbot Assistant](https://calendly.com/url?q=https%3A%2F%2Fsupport.opensolar.com%2Fhc%2Fen-us&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=c8442224eb26c77e21a43dc5b7b0b9d43bb04a2d8c2548c0aa46b7a2408a2773)

*Get real-time live answers to your questions with our digital assistance*

☀️ [General Support Contact Form](https://calendly.com/url?q=https%3A%2F%2Fsupport.opensolar.com%2Fhc%2Fen-us%2Frequests%2Fnew&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=85ad0ab73c3600ce64e605338d66ded3eb63f0f8e3e1429e768a43300f9b7041)

*Send enquiries, feedback and supporting information directly to our global 24 hour Mon - Fri support team. Tickets are the quickest most efficient way to receive support and guidance. <u>Unfortunately, we can only offer very limited low-priority support via email.</u>*

☀️ [1-2-1 Support](https://calendly.com/url?q=https%3A%2F%2Fwww.opensolar.com%2Fwebinars-uk&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=8f14c921c6a7e01774c69e6f909366503046265a105c7e9cd436a0af5fc95769)

*Installers looking for 1-2-1 support can view our availability and book sessions directly. Click "Book a time" at the bottom of the page.*

☀️ [Online Resource Centre](https://calendly.com/url?q=https%3A%2F%2Fsupport.opensolar.com%2Fhc%2Fen-us&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=c8442224eb26c77e21a43dc5b7b0b9d43bb04a2d8c2548c0aa46b7a2408a2773)

*An extensive online library of videos and tutorials.*

**Finance Integrations**

🎥 [Finance Training](https://calendly.com/url?q=https%3A%2F%2Fsupport.opensolar.com%2Fhc%2Fen-us%2Farticles%2F8226089914255%3F&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=4754724a137035b26a2b3335cbf17119798a5cf31795ac45d3087c0041d18d2e)

[**Selina**](https://calendly.com/url?q=https%3A%2F%2Fwww.selinafinance.co.uk%2F&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=76b3982a8002d25f6054709f248c8a2e11fbeb101b28148aaec41e35334a3e53) *(domestic payment plans)*

- Email: tom.watson@selinafinance.co.uk
- Call: 020 4525 8044
- [Register here](https://calendly.com/url?q=https%3A%2F%2Fpages.opensolar.com%2Fpartners%2Fselina&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=b77cfadce24be48322b88be88f413678165dca5acc293657b126fea366a4b2b6)

[**Phoenix Finance**](https://calendly.com/url?q=https%3A%2F%2Fwww.phoenix-fc.co.uk%2F&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=3dea358b2b0d129ea9bc530ab3f2550532b5af1f9fb09d0af0767fc4446c4eb7) *(domestic payment plans)*

- Email: jono@phoenix-fc.co.uk
- Book meetings: [https://calendly.com/jono-9](https://calendly.com/jono-9)
- Call: 01923 333 256
- [Register here](https://calendly.com/url?q=https%3A%2F%2Fwww.opensolar.com%2Fphoenix&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=d0aceee8be4e332e21d7656077cdffd628cfcb4453cfa2f462462ee288cb06de)

[**Smart Ease**](https://calendly.com/url?q=https%3A%2F%2Fsmartease.uk%2F&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=3e13409ae67f477d37e34b6b6d19f4f6302fb791e3a8d037744adf4988c8705f) *(commercial payment plans)*

- Email: enquiries@smartease.uk
- Call: 033 3404 0695
- [Register here](https://calendly.com/url?q=https%3A%2F%2Fwww.opensolar.com%2Fsmartease&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=eb2d0fe99b04186128681c7ee9ec20bb04f6727b86125e1a2625a38b993ecffa)

**Scaffolding Integration**

🎥 [PVF Scaffolding Training](https://calendly.com/url?q=https%3A%2F%2Fsupport.opensolar.com%2Fhc%2Fen-us%2Farticles%2F10670248169743-PVF-Scaffolding-Design-UK%3F&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=1255b2a6ebce7bc5db426704538bb9cfa1925544e21b6e800c3fd4e5abe4506b)

**API Integrations**

[Learn more and view documentation](https://calendly.com/url?q=https%3A%2F%2Fwww.opensolar.com%2Fapi&user_uuid=b04aeb0a-5c6e-4ff3-99c6-fd31f5b8b7a6&stage=1&hmac=0e9f1a634ca29a1083492db339dff02caa1b1ac99e9f113abf9307a5b2a050b7)

# Target Architecture

<div drawio-diagram="96"><img src="https://bookstack.nearlyfreeenergy.com/uploads/images/drawio/2026-06/drawing-4-1782736286.png" alt=""/></div>

# Metering

# Metering Evalutation

<table border="1" id="bkmrk-attribute-cost-%28mone" style="border-collapse: collapse; width: 100%; height: 357.773px;"><colgroup><col style="width: 16.6865%;"></col><col style="width: 16.6865%;"></col><col style="width: 16.6865%;"></col><col style="width: 16.6865%;"></col><col style="width: 16.6865%;"></col><col style="width: 16.6865%;"></col></colgroup><tbody><tr style="height: 46.5938px;"><td style="height: 46.5938px;">Attribute</td><td style="height: 46.5938px;">Cost (money)</td><td style="height: 46.5938px;">Interoperability</td><td style="height: 46.5938px;">long term relationship</td><td style="height: 46.5938px;">Deployment Readiness</td><td style="height: 46.5938px;">Build Quality   
</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Inhemeter   
</td><td style="height: 29.7969px;">3</td><td style="height: 29.7969px;">5</td><td style="height: 29.7969px;">3</td><td style="height: 29.7969px;">3</td><td style="height: 29.7969px;">5</td></tr><tr style="height: 63.3984px;"><td style="height: 63.3984px;">Gomelong Meter (no PLC meter with built-in relay)</td><td style="height: 63.3984px;">  
</td><td style="height: 63.3984px;">  
</td><td style="height: 63.3984px;">  
</td><td style="height: 63.3984px;">  
</td><td style="height: 63.3984px;">  
</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Sagewood Meters</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td></tr><tr style="height: 35.3984px;"><td style="height: 35.3984px;"><span style="color: rgb(22, 145, 121);">[Calin Meter](https://www.prepayment-meter.com/sale-7647501-split-type-sts-prepaid-meters-din-rail-power-meter-with-ciu-pole-mounting.html)</span></td><td style="height: 35.3984px;"><span style="color: rgb(22, 145, 121);">?</span></td><td style="height: 35.3984px;"><span style="color: rgb(22, 145, 121);">5</span></td><td style="height: 35.3984px;"><span style="color: rgb(22, 145, 121);">5</span></td><td style="height: 35.3984px;"><span style="color: rgb(22, 145, 121);">?</span></td><td style="height: 35.3984px;"><span style="color: rgb(22, 145, 121);">5</span></td></tr><tr style="height: 35.3984px;"><td style="height: 35.3984px;">[Spark Meter](https://nextcloud.nearlyfreeenergy.com/f/627)</td><td style="height: 35.3984px;">3</td><td style="height: 35.3984px;">1</td><td style="height: 35.3984px;">3</td><td style="height: 35.3984px;">1</td><td style="height: 35.3984px;">5</td></tr><tr style="height: 46.5938px;"><td style="height: 46.5938px;">China Brandless Meter   
</td><td style="height: 46.5938px;">5</td><td style="height: 46.5938px;">1</td><td style="height: 46.5938px;">3</td><td style="height: 46.5938px;">3</td><td style="height: 46.5938px;">1</td></tr><tr style="height: 35.3984px;"><td style="height: 35.3984px;">[iSmart Meter](https://www.ismartmeters.com/products/single-phase-smart-sts-g3-plc-split-din-rail-prepaid-meter/?utm_source=chatgpt.com)</td><td style="height: 35.3984px;">1</td><td style="height: 35.3984px;">5</td><td style="height: 35.3984px;">3</td><td style="height: 35.3984px;">1</td><td style="height: 35.3984px;">3</td></tr><tr style="height: 35.3984px;"><td style="height: 35.3984px;"><span style="color: rgb(191, 237, 210);">[Hoptele Meter](https://www.hoptele.com/single-phase-energy-meter/)</span></td><td style="height: 35.3984px;"><span style="color: rgb(191, 237, 210);">3</span></td><td style="height: 35.3984px;"><span style="color: rgb(191, 237, 210);">5</span></td><td style="height: 35.3984px;"><span style="color: rgb(191, 237, 210);">5</span></td><td style="height: 35.3984px;"><span style="color: rgb(191, 237, 210);">5</span></td><td style="height: 35.3984px;"><span style="color: rgb(191, 237, 210);">3</span></td></tr></tbody></table>

### Inhemeter

China/UG based OEM. Edwin Cho is our contact. 0 774 667667, +86 135 3210 1631. 1way Meter boxed FOB 46Usd  
Cloud Vending System 100 USD per month up to 1000 meters

Free On Board (FOB)  
Which means not including shipping and inland transport and any clearance fees

### Sagewood   


Sagewood is a UK based logistics supplier. +44 7831 135528 - Manoj

Got some feedback on this one . Here goes… Hi Hilary, all good am still in china snd heading back tomrrow to uk. China was on national holidays from 30 April to today May 5. Now working on it. I have discussed with the team - Due to small number of meters for the system, we suggest a cloud version so you don’t have to invest in hardware. Many endusers are doing this. Meters we can handle but MOQ is around 2000 metres. Or we can manufacture them to very with other orders. So you don’t have to worry about MOQ. Allow me few days and I revert back.

### Hoptele   


China supplier / OEM. Single phase PLC meter. Wall mount with PLC support and inbuilt relay. DIN rail mount with PLC support but no inbuilt relay. 70 US per meter. No vending system.

### Gomelong   


China based supplier, has a local distributor in Uganda. Gomelong Meter (no PLC meter with built-in relay). May have none PLC option. Pricing for "digital meter" (probably with no relay) 127k UGX per unit.

### Spark Meter   


Kenya based. Proprietary system (Meters + AMI). 70 USD per meter. Comes with a DTU that requires line of sight to meters. 1 DTU per 2000 meters max. 600 USD per year per DTU.

### Calinmeter   


Have a DIN rail PLC with built-in relay. Waiting on quote. May also have AMI

### iSmart   


Found these ones online. They also have a [PLC with built-in relay](https://www.ismartmeters.com/products/single-phase-smart-sts-g3-plc-split-din-rail-prepaid-meter/).

<div id="bkmrk-total-cost-for-prepa" style="max-width: 100%;">The meter sample fee: 10pcs*600USD/pc; the DCU will need 7500USD/pc; the PC software for testing is 5000USD/pc; the optical head is 300USD/pc; the pilot system will need 30000USD; the technical assistance fee is 1500USD; DHL shipping cost is around 5500USD.</div>

# Wired vs Wireless meters

### Wireless open standards   


#### Comparison

<table id="bkmrk-protocol-frequency-r"><thead><tr><th>Protocol</th><th>Frequency</th><th>Range</th><th>Data Rate</th><th>Topology</th><th>Power Usage</th></tr></thead><tbody><tr><td>Zigbee</td><td>2.4 GHz, 915/868 MHz</td><td>Short</td><td>Up to 250 kbps</td><td>Mesh, Star</td><td>Very Low</td></tr><tr><td>LoRaWAN</td><td>868/915 MHz</td><td>Long</td><td>0.3–50 kbps</td><td>Star</td><td>Extremely Low</td></tr><tr><td>Wi-SUN</td><td>868/915 MHz</td><td>Medium to Long</td><td>50–300 kbps</td><td>Mesh</td><td>Low to Medium</td></tr><tr><td>Bluetooth LE</td><td>2.4 GHz</td><td>Short</td><td>125 kbps–2 Mbps</td><td>Star, Mesh</td><td>Very Low</td></tr><tr><td>IEEE 802.11ah</td><td>Sub-GHz (~900 MHz)</td><td>Medium</td><td>Up to Mbps</td><td>Star, Tree</td><td>Low</td></tr><tr><td>IEEE 802.15.4</td><td>Various</td><td>Short–Medium</td><td>20–250 kbps</td><td>Mesh, Star</td><td>Very Low</td></tr><tr><td>Thread</td><td>2.4 GHz</td><td>Short</td><td>250 kbps</td><td>Mesh</td><td>Very Low</td></tr></tbody></table>

#### Recommended for Residential Microgrid Applications in Uganda:

- **LoRaWAN**: If covering a large geographical area (kilometers), due to its excellent range, penetration, and low power use.
- **Wi-SUN**: For robust, medium-to-large-scale smart metering networks, especially if a mesh topology is desirable.
- **Zigbee/Thread**: Ideal for dense residential areas where devices (meters) are closer together, benefiting from low power and reliable mesh networking.

### Wired Open standards   


#### Comparison

<table id="bkmrk-protocol-standard-os"><thead><tr><th>Protocol</th><th>Standard</th><th>OSI Layers</th><th>Medium</th><th>Topology</th><th>Range</th><th>Data Rate</th><th>Typical Application Areas</th><th>Remarks</th></tr></thead><tbody><tr><td>**G3-PLC**</td><td>ITU-T G.9903</td><td>Layers 1-2</td><td>Power Lines</td><td>Mesh, Star</td><td>Up to several km</td><td>2.4–35 kbps</td><td>Smart grids, AMI, smart meters</td><td>Robust, designed for noisy environments; supports IPv6, strong security</td></tr><tr><td>**PRIME**</td><td>ITU-T G.9904</td><td>Layers 1-2</td><td>Power Lines</td><td>Mesh, Star</td><td>Up to several km</td><td>21–128 kbps</td><td>Smart metering, distribution automation</td><td>Optimized for higher-speed PLC, widely used in European smart meter rollouts</td></tr><tr><td>**IEEE 1901.2 PLC**</td><td>IEEE 1901.2</td><td>Layers 1-2</td><td>Power Lines</td><td>Mesh, Star</td><td>Up to several km</td><td>2.4–500 kbps</td><td>Smart grids, smart cities</td><td>High interoperability, IPv6 support; ideal for utility and smart city deployments</td></tr><tr><td>**M-Bus (Meter-Bus)**</td><td>EN 13757</td><td>Layers 1-2</td><td>Twisted pair cable</td><td>Bus</td><td>Up to ~1 km</td><td>0.3–38.4 kbps</td><td>Meter reading (water, heat, gas)</td><td>Widely used in Europe; reliable, low-cost wired solution</td></tr><tr><td>**KNX**</td><td>ISO/IEC 14543-3</td><td>Layers 1-2</td><td>Twisted pair cable</td><td>Bus, Star, Tree</td><td>Up to ~1 km</td><td>9.6 kbps</td><td>Building automation, home control</td><td>Open standard for building automation, popular in Europe</td></tr><tr><td>**BACnet MS/TP**</td><td>ASHRAE 135</td><td>Layers 1-2</td><td>RS-485 twisted pair</td><td>Bus</td><td>Up to ~1.2 km</td><td>9.6–115.2 kbps</td><td>Building automation, HVAC controls</td><td>Common in building and industrial automation; robust, scalable</td></tr><tr><td>**Ethernet**</td><td>IEEE 802.3</td><td>Layers 1-2</td><td>CAT5/CAT6 cable</td><td>Star, Tree</td><td>Up to ~100 m</td><td>10 Mbps–100 Gbps</td><td>Networking backbone, smart buildings</td><td>High-speed, standard networking; widely supported across industries</td></tr><tr><td>**RS-485 (EIA-485)**</td><td>EIA-485</td><td>Layers 1-2</td><td>Twisted pair cable</td><td>Bus</td><td>Up to ~1.2 km</td><td>Up to 10 Mbps</td><td>Metering, industrial control systems</td><td>Simple, robust, widely used for serial data transmission</td></tr><tr><td>**CAN Bus**</td><td>ISO 11898</td><td>Layers 1-2</td><td>Twisted pair cable</td><td>Bus</td><td>Up to ~1 km</td><td>Up to 1 Mbps</td><td>Automotive, industrial automation</td><td>High reliability, robust error detection, common in harsh environments</td></tr></tbody></table>

#### Recommended Wired Protocols for Residential Microgrid Metering (Uganda)

- **PLC-based (e.g., G3-PLC or IEEE 1901.2)**:
    
    
    - Ideal due to existing infrastructure (power lines).
    - Good for scalable, reliable deployments.
- **RS-485**:
    
    
    - Robust, simple wiring suitable for smaller clusters.
    - Common for direct-wired connections (local clusters).
- **M-Bus**:
    
    
    - Suitable if integrating gas, water, or heat metering alongside electricity

### Comparison between wired and wireless   


<table id="bkmrk-aspect-wireless-opti"><thead><tr><th>Aspect</th><th>Wireless Option (Wi-SUN/LoRaWAN)</th><th>Wired Option (G3-PLC, RS-485)</th><th>Recommendation</th></tr></thead><tbody><tr><td>**Installation Cost**</td><td>🟢 Lower</td><td>🔴 Higher (cabling, labor)</td><td>Wireless ✅</td></tr><tr><td>**Maintenance Cost**</td><td>🟡 Moderate (battery replacements)</td><td>🟢 Low (no batteries required)</td><td>Wired ✅</td></tr><tr><td>**Reliability**</td><td>🟡 Medium (environment dependent)</td><td>🟢 High (consistent, stable)</td><td>Wired ✅</td></tr><tr><td>**Scalability**</td><td>🟢 High (easy additions)</td><td>🔴 Moderate to low (harder additions)</td><td>Wireless ✅</td></tr><tr><td>**Range/ Coverage**</td><td>🟢 Good (with repeaters)</td><td>🟢 Excellent (using PLC)</td><td>Wired (PLC) ✅</td></tr><tr><td>**Security**</td><td>🟡 Good (depends on setup)</td><td>🟢 Very Good</td><td>Wired ✅</td></tr><tr><td>**Installation Time**</td><td>🟢 Short</td><td>🔴 Longer</td><td>Wireless ✅</td></tr><tr><td>**Physical disruption**</td><td>🟢 Minimal</td><td>🔴 High (trenching, wiring)</td><td>Wireless ✅</td></tr></tbody></table>

### 💡 Recommended Choice: Hybrid or G3-PLC

#### 📌 Primary Recommendation: G3-PLC (Wired)

Given your scenario (dense apartment blocks with existing electrical infrastructure and meters located closely on the ground floor), **G3-PLC** offers significant advantages:

- **Low Ongoing Maintenance:** No batteries to manage.
- **High Reliability:** Stable signal leveraging existing wiring.
- **Cost-effective (long-term):** Minimal ongoing costs after initial installation.
- **Robust &amp; secure**: Highly suited for apartment complexes.

#### 📌 Alternate Recommendation: Hybrid (PLC Backbone + Wireless Endpoints)

If flexibility or future expansions matter, consider a hybrid setup:

- Use **G3-PLC** within each block to connect meters reliably to a local gateway.
- Connect block gateways to a central system via wireless (**Wi-SUN or LoRaWAN**). This reduces physical disruption between buildings while maintaining the reliability within each block.

This hybrid method provides the best of both worlds—flexibility and low maintenance.

### Links

[Chatgpt detailed thread](https://chatgpt.com/share/682665f4-9c6c-800c-a63f-6d58c790a91a)

# CalinMeter

We got the API docs here: [Calin\_API\_for\_NFE.postman\_collection.json](https://bookstack.nearlyfreeenergy.com/attachments/60)

#### User Manuals 

- [User instructions for the CA168-S Single-phase electricity meter (1).pdf](https://bookstack.nearlyfreeenergy.com/attachments/51)
- [CA168 Din Rail Meter- Technical Specification (1).pdf](https://bookstack.nearlyfreeenergy.com/attachments/52)
- [Installation Guide - Calin LoraWAN Smart Meters.pdf](https://bookstack.nearlyfreeenergy.com/attachments/53)

# **⚡ CalinMeter Status Codes – Postpaid Quick Reference &amp; Action Guide**

---

## **📑 Common Meter Status / Short Codes (Postpaid Use)**

<table id="bkmrk-code-meaning-action-"><thead><tr><th>**Code**

</th><th>**Meaning**

</th><th>**Action**

</th></tr></thead><tbody><tr><td>01

</td><td>Cumulative total active kWh consumption

</td><td>Record/check usage trend

</td></tr><tr><td>14

</td><td>Load threshold

</td><td>Compare with customer load, adjust if configured too low

</td></tr><tr><td>31

</td><td>Current total active power

</td><td>Check load at moment of query

</td></tr><tr><td>35

</td><td>Current total power factor

</td><td>If persistently low, investigate load/PF correction

</td></tr><tr><td>40

</td><td>Number of meter cover open events

</td><td>Check tamper log; reseal if necessary

</td></tr><tr><td>41–45

</td><td>Last 1st–5th cover open times

</td><td>Verify tamper history

</td></tr><tr><td>46

</td><td>Number of overload trip events

</td><td>Review load demand; advise upgrade if frequent

</td></tr><tr><td>47–51

</td><td>Last 1st–5th overload trip times

</td><td>Identify when overloads occurred

</td></tr><tr><td>52

</td><td>Number of power down events

</td><td>Check supply reliability

</td></tr><tr><td>53–57

</td><td>Last 1st–5th power down times

</td><td>Cross-check with outage records

</td></tr><tr><td>58

</td><td>Number of phase down events

</td><td>Investigate supply-side issues

</td></tr><tr><td>87

</td><td>Reason for relay disconnecting

</td><td>Use table below for action

</td></tr></tbody></table>

*(Codes related to credit/tokens are ignored in postpaid setups.)*

Perfect — let’s build a <span class="s1">**lookup table**</span> that maps your AMI responses (1000–1025) directly to the <span class="s1">**Code 87 disconnect sub-codes**</span>, with <span class="s1">**meaning**</span> and <span class="s1">**field action**</span> tailored for <span class="s1">**postpaid deployments**</span>.

# ⚡ AMI Operating Status Code Lookup (Postpaid Mode)

<table id="bkmrk-ami-code-code-87-sub"><thead><tr><th>**AMI Code**

</th><th>**Code 87 Sub-Code**

</th><th>**Meaning**

</th><th>**Field Action**

</th></tr></thead><tbody><tr><td>**1000**

</td><td>00

</td><td>Relay Closed (normal supply)

</td><td>✅ No action, meter supplying load.

</td></tr><tr><td>**1001**

</td><td>1

</td><td>No Credit

</td><td>*(Ignore in postpaid)* — not applicable.

</td></tr><tr><td>**1003**

</td><td>3

</td><td>Over Power (load exceeded threshold)

</td><td>Check load vs. configured trip limit; advise reduction or adjust threshold.

</td></tr><tr><td>**1004**

</td><td>4

</td><td>Relay Test

</td><td>No action needed — relay was tested.

</td></tr><tr><td>**1005**

</td><td>5

</td><td>Open Upper Cover (tamper)

</td><td>Reseal cover + enter clear tamper token.

</td></tr><tr><td>**1006**

</td><td>6

</td><td>Open Terminal Cover (tamper)

</td><td>Reseal cover + enter clear tamper token.

</td></tr><tr><td>**1007**

</td><td>7

</td><td>Remote Disconnect

</td><td>Confirm backend/HES instruction; reconnect if not intentional.

</td></tr><tr><td>**1008**

</td><td>8

</td><td>Not-active (meter not commissioned)

</td><td>Commission meter (default code: 12345).

</td></tr><tr><td>**1009**

</td><td>9

</td><td>Over Current

</td><td>Inspect load for surges; advise customer or adjust protection.

</td></tr><tr><td>**1011**

</td><td>11

</td><td>Over Voltage

</td><td>Supply voltage too high; report to utility/feeder operator.

</td></tr><tr><td>**1012**

</td><td>12

</td><td>Under Voltage

</td><td>Supply voltage too low; report to utility/feeder operator.

</td></tr><tr><td>**1013**

</td><td>13

</td><td>Current Reverse (possible tamper/wiring issue)

</td><td>Inspect wiring; correct polarity; clear tamper if needed.

</td></tr><tr><td>**1014**

</td><td>14

</td><td>Open Enclosure Cover (tamper)

</td><td>Reseal + enter clear tamper token.

</td></tr><tr><td>**1015**

</td><td>15

</td><td>Magnetic Field Interference (tamper)

</td><td>Investigate possible magnet tampering; clear tamper.

</td></tr><tr><td>**1016**

</td><td>16

</td><td>Current Imbalance

</td><td>Check for abnormal phase imbalance; troubleshoot load.

</td></tr><tr><td>**1017**

</td><td>17

</td><td>Neutral Line Interference

</td><td>Inspect neutral wiring/tamper.

</td></tr><tr><td>**1018**

</td><td>18

</td><td>Bypass (illegal connection)

</td><td>Investigate and escalate if confirmed.

</td></tr><tr><td>**1021**

</td><td>21

</td><td>Voltage Imbalance

</td><td>Investigate feeder phase imbalance.

</td></tr><tr><td>**1022**

</td><td>22

</td><td>Thermal Overload

</td><td>Meter overheating; check ventilation/load; allow cooling.

</td></tr><tr><td>**1023**

</td><td>23

</td><td>Low Power Factor

</td><td>Check load PF; recommend correction (capacitors).

</td></tr><tr><td>**1024**

</td><td>24

</td><td>Tariff Error

</td><td>Backend tariff configuration issue; escalate to AMI admin.

</td></tr><tr><td>**1025**

</td><td>25

</td><td>Remote Reconnect + Local Trip

</td><td>Local condition (e.g., overload/tamper) persists; troubleshoot before reconnection.

</td></tr></tbody></table>

---

<span class="s2">✅ </span>**Key Notes for Postpaid Teams**

- <span class="s1">**Ignore credit-related codes**</span> (1001, and codes tied to tokens/residual amounts).
- <span class="s1">**Focus on tamper (1005, 1006, 1014, 1015, 1018)**</span>, load/power quality (1003, 1009, 1011–1013, 1016–1023), and backend issues (1007, 1024, 1025).
- <span class="s1">**Always check AMI Code → Action**</span> before deciding if a site visit is required.

---

Would you like me to now <span class="s3">**regenerate the PDF reference card**</span> with this full <span class="s3">**1000–1025 lookup table**</span> included, so your team doesn’t need to flip between guides?

<span class="s2">✅ </span>**Quick Action Guide Summary**

- <span class="s1">**Tamper-related (5, 6, 14, 15, 18)**</span> → Reseal + enter clear tamper token.
- <span class="s1">**Load/power issues (3, 9, 11, 12, 16, 21, 22, 23)**</span> → Inspect loads and supply conditions; report or advise customer.
- <span class="s1">**Backend-related (7, 24, 25)**</span> → Confirm with HES/AMI admin.
- <span class="s1">**Commissioning (8)**</span> → Activate with code 12345.

### Examples

#### Example #1

You query the meter for meter operating status and you get back this

[![Screenshot 2025-09-04 at 14.21.36.png](https://bookstack.nearlyfreeenergy.com/uploads/images/gallery/2025-09/scaled-1680-/screenshot-2025-09-04-at-14-21-36.png)](https://bookstack.nearlyfreeenergy.com/uploads/images/gallery/2025-09/screenshot-2025-09-04-at-14-21-36.png)

#### Answer 

**Meter operating status = 1008**

**Step 1: Interpret the Code**

- In many AMI/CalinMeter integrations, codes like <span class="s1">**1000**</span> and <span class="s1">**1008**</span> map directly to <span class="s1">**relay/disconnect statuses (Code 87 sub-codes)**</span>.
- **1008 = Sub-code 8 under Code 87**<span class="s1">.</span>
- From the guide:
    
    
    - <span class="s1">**8 → “Not-active”**</span> → *Meter not commissioned*.

**Step 2: What This Means in Postpaid Setup**

- The meter is physically installed, but it hasn’t been <span class="s1">**commissioned**</span>.
- In this state, the meter will <span class="s1">**not supply power**</span>, regardless of load or tariff configuration.

**Step 3: Field Action (from Quick Action Guide)**

- <span class="s1">**Action**</span>: Commission the meter using the <span class="s1">**commissioning token/code**</span>.
    
    
    - Default commissioning code is <span class="s1">**12345**</span>.
    - Enter this via the CIU (Customer Interface Unit) or backend if supported.
- Once successfully commissioned:
    
    
    - Tamper detection is activated.
    - Relay will close and supply will start flowing.

<span class="s3">✅ </span>**Summary:**

<span class="s3">Your AMI response of </span>**1008**<span class="s3"> means </span>**“Meter not commissioned.”**

👉 To resolve: Enter <span class="s1">**12345**</span> (or your site-specific commissioning token) on the CIU/backend to activate the meter.

---

#### Example #2 

[![Screenshot 2025-09-04 at 14.36.50.png](https://bookstack.nearlyfreeenergy.com/uploads/images/gallery/2025-09/scaled-1680-/screenshot-2025-09-04-at-14-36-50.png)](https://bookstack.nearlyfreeenergy.com/uploads/images/gallery/2025-09/screenshot-2025-09-04-at-14-36-50.png)

#### Answer

Great — let’s now map <span class="s1">**1000**</span> through the same guide.

Case: Meter operating status = 1000

**Step 1: Interpret the Code**

- In the AMI integration, <span class="s1">**1000**</span> corresponds to <span class="s1">**Code 87 sub-code 00**</span>.
- **00 → “Relay Closed”**<span class="s1">.</span>

**Step 2: What This Means in Postpaid Setup**

- <span class="s1">The meter is </span>**active and commissioned**<span class="s1">.</span>
- The <span class="s1">**relay is closed**</span>, meaning the meter is supplying electricity normally.
- No tamper or abnormal condition is blocking supply.

**Step 3: Field Action (from Quick Action Guide)**

- <span class="s1">**Action**</span>: No intervention needed.
- Record this status if troubleshooting, since it confirms the meter is healthy and delivering power.

<span class="s3">✅ </span>**Summary for your case:**

<span class="s3">Your AMI response of </span>**1000**<span class="s3"> means </span>**“Relay Closed – supply ON.”**

👉 Everything is normal; no technician action required.

⚡ So together:

- **1000 = Relay Closed (meter supplying power)**
- **1008 = Not-active (meter not commissioned; activate with commissioning code)**

# A2EI Data

Thank you for showing interest in our data and our efforts here at the A2EI!

We are happy to provide you with our latest data releases from our <span class="nf-setting-groups"><span class="nf-field-settings">Solar Killed the Generator Star Project in Nigeria, our </span></span>clean cooking pilots, and our research into productive-use appliances in East Africa. Please find a detailed summary of each dataset and latest release below.

Please drop us a line via datadatadata@a2ei.org if you have any comments or questions, or in case you would like to unsubscribe from receiving updates.

<u>Most recent data releases SKGS</u>

<span class="nf-setting-groups"><span class="nf-field-settings"><u>06.04.2022</u></span></span> The A2EI set out to provide the sector with an open-source hardware  
solar business system. Two years later, we have not only made the solar  
generator available, but sold over 1,000 systems. Every solar  
generator is sending real time data on consumption and system state,  
which allows the A2EI to share millions of data points with the sector  
as open-source data.

Please download our [SKGS Project Update and Data Release Report here](https://a2ei.org/resources/uploads/2022/04/A2EI_SKGS_project_update_data_release.pdf)<u>[.](https://a2ei.org/resources/uploads/2022/04/A2EI_SKGS_project_update_data_release.pdf)</u>

<span class="nf-setting-groups"><span class="nf-field-settings">Download the </span></span>[associated data and readme here.](https://a2ei.org/resources/uploads/2022/04/A2EI_SKGS_data_release_April2022.zip)<u>  
</u>  
<span class="nf-setting-groups"><span class="nf-field-settings"><u>29.04.2020</u></span></span> To  
date, we have over 215 smart meters (and counting) connected to small  
scale generators and grids in Nigeria, located within multiple markets  
across several regions.  
You can download the raw data, the meter list as well as the README [here](https://drive.google.com/drive/folders/162VRGDNgoEDTc2fXoyVdsjyqrwXkOdtj).  
Find some brief release notes [here](https://a2ei.org/resources/uploads/2021/05/Release-Notes.pdf).  
Please find the Executive Summary [here](https://a2ei.org/resources/uploads/2020/04/A2EI_data_release_no2_290420.pdf).

<span class="nf-setting-groups"><span class="nf-field-settings"><u>02.06.2020</u></span></span> Please find our analysis of generator usage during COVID-19 [here](https://a2ei.org/resources/uploads/2020/06/A2EI_Effects_of_COVID-19_on_generator_usage_in_AbujaLagos.pdf).

<u>Latest data releases Clean Cooking  
</u>  
<span class="nf-setting-groups"><span class="nf-field-settings"><u>15.11.2021</u> I</span></span>n a new comprehensive data release report, the A2EI analyses the entire data collected by our smart meters monitoring the usage of electric pressure cookers (EPCs) by 100 pilot users in rural Tanzania from March 2020 to May 2021.  
Please [download the data release report here.](https://a2ei.org/resources/uploads/2021/11/A2EI_Clean_Cooking_Data_Release_Report_Nov2021.pdf)  
Download the data frames [here](https://a2ei.org/resources/uploads/2021/11/DATA_A2EI_clean_cooking_Tanzania_data_release_November2021.zip).  
Download the Readme [here](https://a2ei.org/resources/uploads/2021/11/README_A2EI_clean_cooking_Tanzania_data_release_November2021.pdf).

<span class="nf-setting-groups"><span class="nf-field-settings"><u>16.07.2021</u></span></span> The A2EI has been part of a feasibility study to pave the way for mass distribution of electric hotplates to rural households in Malawi. Please download the Study of Hotplate &amp; Grid Use in Rural Malawi [here](https://a2ei.org/resources/uploads/2021/07/A2EI_Study-of-Hotplate-and-Grid-Use-in-Rural-Malawi.pdf) and access the associated data [here](https://a2ei.org/resources/uploads/2021/07/a2ei_data_hotplate.zip).  
<u>  
</u>

<u>Latest data releases Productive Use</u>

<span class="nf-setting-groups"><span class="nf-field-settings"><u>14.07.2021</u> We are sharing our learnings of successful ventures in the agricultural productive use appliance sector by our first "Entrepreneur in Residence", Imara Tech, and are proposing a way forward that we believe could increase the likelihood for successful product development.<span class="sewqrq0uonxqsyc"> Download the [summary of learnings here](https://a2ei.org/resources/uploads/2021/07/A2EI-Productive-Use-Machinery-in-Agriculture.pdf).</span></span></span><u>  
</u>  
<span class="nf-setting-groups"><span class="nf-field-settings"><u>21.09.2020</u></span></span> The Access to Energy Institute has developed a systematic methodology and published a report to jointly discuss the question what makes or breaks a successful solar-powered productive-use appliance - and to help find solutions for successful adoption and scaling.  
Download the report [here](https://a2ei.org/resources/uploads/2020/09/A2EI_Productive_Use_Report_Agricultural_Technologies.pdf).  
Please find the associated data and materials [here](https://a2ei.org/resources/uploads/2020/09/A2EI-Productive-Use-Worksheets_2.xlsx)<u>.</u>

Your feedback is very warmly welcomed. We believe that sharing our data is paramount to unlocking further entrepreneurship and engineering, which in turn will help us crack the many nuts of providing a reliable, clean and affordable universal energy supply. In our efforts to deliver meaningful data, we need your feedback in order to collect further data points and to make adjustments to our current measuring practices.

For now, we wish you a wonderful day...and cheerful data crunching!

All the best,  
your A2EI Team

# NFE metering strategy + Glen Street-EMS

> Authoritative page for NFE's role in the IEEE Smart Village meshEMS / Street-EMS initiative. Compiled 2026-08-10 from the Element room "Smart Village Energy Interest Group" (full history back to 2026-04-24), the ISV Dev Kit BOM sheet, isv.wiki, and the Rev B/C line diagrams. No customer PII or financial ledgers on this page by policy.

## What it is

Not a standalone NFE product. It is NFE's seat in an IEEE Smart Village (ISV) open-source initiative called **meshEMS**, hardware-branded **Street-EMS**, started at an IEEE / NESL hackathon in April 2026. Hardware and firmware are led by Glenn Algie (10power.com / NESL); the software and standards side is led by Adam Sauer (ISV Tech Committee chair). The working venue is the Element/Matrix room "Smart Village Energy Interest Group".

**meshEMS** is open-source firmware on an ESP32-S3 / ESP32-P4 module doing **OpenAMI two-way metering and control over secure MQTT into OpenEMS**. Deployed as a street-pole or pedestal **low-voltage feeder cabinet** that meters AND controls every tenant, it is designed to replace the per-tenant DIN-rail meters and the OpenEMS Raspberry Pi with a single integrated 9x15 cm EMS board.

Three related code bases (grown by 10power.com with two grad EE engineers on a 90-day sprint): **Street-EMS**, **BUILD-EMS**, **DTM-EMS**. GitHub org: `github.com/energy-iot` (`ems-dev` = Street-Pole EMS, `nesl-meshems` = the board, `openami-smart-village`, `meshems-openami-metering`).

## How it fits NFE

- **Today (pilot):** CHINT DDSU666 smart meters plus a Raspberry Pi gateway over Modbus RTU / RS485, feeding OpenEMS. Current pedestal cabinet is roughly 80 x 60 x 25 cm, about USD 150 locally.
- **Next generation:** the Street-EMS cabinet folds the 3-phase meter, the per-tenant meters and the Pi into one EMS board plus an SSR bank, shrinking the cabinet (cheaper, fits indoor locations, easier to secure from theft and weather) and adding per-tenant remote control and local energy-policy automation.

## The cabinet (Rev C, 9-tenant, 3-phase LV feeder)

Signal flow left to right:

- **Incoming LV feeder** L1/L2/L3 + N + PE. Each phase: a 63A main breaker (QF1/QF2/QF3), a mains-usage CT (CT4/CT10/CT16), then a UKK80 terminal block fanning out to up to 6 tenant ways per phase.
- **Three Ivy RCMs** (RCM1/2/3), one residual-current monitor per phase, for continuous leakage and neutral insight. Modbus UART to RS485 adaptor.
- **Nine contactors K1..K9** (3 tenants per phase) for per-tenant remote connect/disconnect, each with a tenant-usage CT (CT1,2,3,7,8,9,13,14,15).
- **Controller on the cabinet door:** "Street-EMS w RGBW" = 3 stacked CircuitSetup 6-channel CT meters = 18 channels (9 tenant + 3 mains + 6 spare).
- **Two 8-channel opto-isolated zero-crossing SSRs** drive the 9 contactor coils (9 control lines, 3x3 per phase, 240 Vac sensitive).
- **Backplate Power PCB:** fused, TVS surge protected, 3x Myrra 44122 240-to-9 Vac, giving 5V 2A and 12V 1A.

Legend (Rev B with legend): QF circuit breaker, CT current transformer, K contactor, UKK80 distribution terminal block, RCM residual current monitor, SSR solid-state relay, PCB printed circuit board, EVSE EV charger. 1P+N one phase plus neutral. RS485 / Modbus UART / I2C communications.

**Decisions ratified in the room (2026-07-25):**
- **1P over 1P+N** for tenant breakers and contactors (1P is cheaper; do not switch neutral except for EV).
- **80A over 63A** rating, chosen to leave room for a future EV station at a new location later this year.
- Rev B to Rev C added the legend; the diagram is deemed complete with only a few unlabelled wires to clarify at the workshop.

**Still open:** the make-before-break 80A neutral / phase-transfer balancer ("neutral rebalancer transfer method and apparatus") and the EVSE port are marked spare-room / in-progress.

## Firmware and energy-policy vision (Glenn)

Local, IFTTT-style per-tenant automation in C/C++ on the ESP32, not just remote on/off:

- **Triggers:** prepaid-token expiry, over-voltage, over-current, over-kW, over-kWh, over-generation, over-storage.
- **Actions:** SSR disconnect (normally-closed contactor coil), SMS alert, RGBW LED or e-paper warning at the tenant box, a flash-warning cadence before cutoff, and a graceful post-sunset lighting-only allowance (about 10-20 W for a few hours from battery when storage allows).
- **Policy model:** each tenant has a JSON "mode" (safety vs prepaid-shutdown automations) stored in ESP32 SPIFFS or SD as a persistent energy-model cache.
- **Grid insight:** continuous per-phase leakage detection, neutral-imbalance alerts, phase-loss detection.

## Cloudless village

An ESP32-P4 with its own Ethernet NIC acts as a per-feeder aggregation node. Street-EMS units LAN-hop along the feeder ("feeder hops") to run an in-village pay-go portal and full UX with no broadband. Optional LoRa / Meshtastic mesh and power-line communication on top; optional low-cost village camera / audio snapshots.

## Standards and interoperability (OpenAMI)

OpenAMI is the "actionable energy telemetry" layer, the utility-facing layer above a village feeder. Built on DLMS/COSEM (IEC 62056), SunSpec Modbus/JSON, MQTT, IEEE 1547-2018 (DER interconnection) and IEEE 2030.5 (Smart Energy Profile). Village Metering goals: billing, remote disconnect, theft detection. EnAccess Foundation is extending the OpenAMI codeset. Reference: isv.wiki (repo `github.com/overview-solutions/isv-ai-wiki`, MIT).

## The workshop (immediate driver of the ISV Dev Kit BOM)

IEEE ISV awarded Glenn and Adam a **4-session, 9-hour hands-on workshop** (assemble an EMS in about 15 minutes each, assemble a cabinet, run code challenges). **IEEE funds the parts BOM.** Plan: build 15-20 EMS units and 3-5 multitenant cabinets for participants to take home (about USD 50 each). Parts pre-ship to Albert, the ISV lead in Nairobi (AliExpress China to Nairobi direct; small PCB parts hand-carried, PSUs prebuilt on site). BOM total about USD 2,377 per batch (see the ISV Dev Kit BOM sheet).

**Venues:** PAC2026 Nairobi (September) and OSEAS Kigali, Rwanda (October, about EUR 50).

**NFE attendance (as of 2026-08-10):** Dansturn and Dismas are going to Kenya (Nairobi). Aaron, now back in Uganda, could join them. Kigali remains a possibility. Glenn asked NFE to co-lead the cabinet builds.

## People and orgs

Glenn Algie (10power.com / NESL / IEEE ISV, hardware + firmware; also WMAC.CLOUD New Zealand, REI Cameroon). Adam Sauer (ISV Tech Committee chair, meshems software + OpenAMI, runs isv.wiki). Aaron Tushabe, Hillary Arinda, Dansturn, Dismas (NFE). Albert (ISV Nairobi lead). Abiodun Okunola (ISV Africa regional lead). EnAccess Foundation, EPRI Open Source, NESL.

## Sources

- Element room "Smart Village Energy Interest Group" (`#smartvillage:matrix.nearlyfreeenergy.com`), full history from 2026-04-24.
- ISV Dev Kit BOM (Google Sheet `1AeAUrfL-Fu_j3xsBPjY555B0huxV0nnMtRjkDTFPjTE`).
- Line diagrams saved at `NFE/smart village energy interest group/` (Rev B with legend, Rev C editable + PDF).
- isv.wiki; `github.com/energy-iot`.

## Open items

- Confirm the Rev C legend back to Glenn (he asked).
- Decide and mobilize the NFE workshop attendance (Nairobi confirmed for Dansturn + Dismas; Aaron + Kigali possible).
- Fill the detailed per-tenant "Behind the Meter" companion page.

# Phase Balancing Recommendation (Sezibwa)

Recommendation for re-assigning Sezibwa's single-phase customers across the three phases of the SRNE three-phase inverter, to fix a severe load imbalance. Uses meter IDs; the site operator maps these to customers.

## Implementation status (2026-08-24)

The two minimal phase-balancing moves were completed on the morning of 2026-08-24:

- **Completed:** meter 003 moved from L1 to L2.
- **Completed:** meter 009 moved from L2 to L3.
- **Outstanding (optional):** meter 004 remains on L3; the optional move from L3 to L1 was not completed.

The expected post-change distribution is L1 5.9 / L2 7.3 / L3 7.6 kWh/day (28 / 35 / 37 percent), based on the historical load profile. Live measurements should be reviewed after sufficient post-change data has accumulated to confirm the achieved balance.

## Baseline before the change (the problem)

Before the 2026-08-24 reconnections, meter_100's per-phase energy and per-customer voltage matching (all high-confidence), the current assignment and daily load is:

| Phase | Load (kWh/day) | Share | Customer meters (kWh/day) |
| --- | --- | --- | --- |
| L1 | 10.4 | 50 percent | 002 (5.7), 003 (4.5), 008 (0.1), 011 (0.1) |
| L2 | 5.1 | 25 percent | 009 (2.3), 007 (1.6), 010 (1.2) |
| L3 | 5.3 | 25 percent | 006 (2.7), 005 (2.1), 004 (0.5) |

Total site load about 20.7 kWh/day, so the ideal is about 6.9 kWh/day per phase. **L1 carries half the site** while L2 and L3 carry a quarter each.

**Root cause:** the two largest consumers, meter 002 (5.7) and meter 003 (4.5), are both on L1. Together they are 10.2 kWh/day, which already exceeds a balanced phase on its own.

## Updated meter reference (after 2026-08-24 phase balancing)

This table records the wiring after the two completed moves. Initials only (no full names, per the customer-data rule). Modbus address is the meter's slave address; serial is the physical meter serial. Energy figures are historical averages used for the recommendation, not post-change measurements.

| Meter | Modbus addr | Serial | Customer (initials) | Previous phase | Current phase | Change status | Historical kWh/day |
| --- | --- | --- | --- | --- | --- | --- | --- |
| meter_002 | 2 | 200326019929 | NP | L1 | L1 | Unchanged | 5.7 |
| meter_003 | 3 | 200326020101 | KFH | L1 | L2 | **Moved 2026-08-24** | 4.5 |
| meter_004 | 4 | 200326020199 | AB | L3 | L3 | Optional L3→L1 move outstanding | 0.5 |
| meter_005 | 5 | 200326020128 | KFH | L3 | L3 | Unchanged | 2.1 |
| meter_006 | 6 | 200326020209 | WS | L3 | L3 | Unchanged | 2.7 |
| meter_007 | 7 | 210302003356 | JN | L2 | L2 | Unchanged | 1.6 |
| meter_008 | 8 | 200326019807 | PO | L1 | L1 | Unchanged | 0.1 |
| meter_009 | 9 | 250902040373 | DK | L2 | L3 | **Moved 2026-08-24** | 2.3 |
| meter_010 | 10 | 250902040216 | SN | L2 | L2 | Unchanged | 1.2 |
| meter_011 | 11 | 250902040311 | (unmapped) | L1 | L1 | Unchanged | 0.1 |

KFH holds two meters (003 and 005), now split across L2 and L3. Names are looked up live from the customer database by serial; the logical-to-service-ID map in the logger configuration had 009/010 transposed, so the physical serial remains authoritative.

## Why phase balance matters

1. **Voltage quality.** L1 carries roughly twice the current of L2/L3, so it has the largest voltage drop. Customers on L1 see the lowest voltage (dimmer lights, more appliance stress) while L2/L3 sit high. Balancing evens the voltage across customers.
2. **Backup capacity.** The SRNE is a three-phase inverter with a per-phase output limit. During a grid outage (battery backup), an overloaded L1 can hit its per-phase limit and trip or brown out even though L2 and L3 have spare capacity and the total is within the inverter rating. Balancing maximises the backup the site can actually deliver.
3. **Losses.** Imbalance drives neutral current and extra I2R losses in the distribution.

Note: this does **not** affect the battery arbitrage or solar economics. The three-phase inverter time-shifts the site's *total* energy across all phases, so the savings analysis is unchanged. Phase balancing is a separate power-quality and backup-reliability issue.

## Implemented recommendation (minimal moves)

The following two reconnections were completed on 2026-08-24:

1. **Completed: meter 003 (4.5 kWh/day) moved from L1 to L2** — the key move, separating the two big loads (002 and 003).
2. **Completed: meter 009 (2.3 kWh/day) moved from L2 to L3** — rebalances L2 after taking on 003.

Expected result based on the historical load profile:

| Phase | Before | After 2 moves |
| --- | --- | --- |
| L1 | 10.4 (50 percent) | 5.9 (28 percent) |
| L2 | 5.1 (25 percent) | 7.3 (35 percent) |
| L3 | 5.3 (25 percent) | 7.6 (37 percent) |

The max-minus-min spread drops from 5.3 to 1.7 kWh/day.

**Outstanding optional third move for near-perfect balance:** meter 004 (0.5) remains on L3. Moving it from L3 to L1 would give L1 6.4 / L2 7.3 / L3 7.1 (31 / 35 / 34 percent), spread 0.9.


## The calculation

- Total daily energy about 20.7 kWh across three phases, so ideal is 20.7 / 3 = 6.9 kWh/day per phase.
- Current spread (heaviest minus lightest): 10.4 - 5.1 = 5.3 kWh/day.
- After the two moves: 7.6 - 5.9 = 1.7 kWh/day.
- After the optional third move: 7.3 - 6.4 = 0.9 kWh/day.

Loads are from the same meter data used across the Sezibwa economic analysis (meter_100 aggregate plus per-customer meters, over the March to August 2026 window). Note that meters 003 and 005 belong to the same customer (two service points); moving 003 to L2 leaves that customer with one meter on L2 and one on L3, which is fine.

## Data provenance

Underlying data: the aggregate meter meter_100 plus the 10 customer sub-meters, over **2026-03-19 to 2026-08-10**, from the modbus energy-logger archive (sources: pi-direct and nextcloud-import), i.e. the pre- and early-OpenEMS period. Load basis is a conservative 21.3 kWh/day.

Note (2026-08-20): the site has since migrated to **OpenEMS**, which is now the live source. OpenEMS-sourced daily figures from mid-August show inconsistencies (the aggregate roughly doubled exactly at the source switchover, and on some days the customer-meter sum exceeds the aggregate), so they are treated as a data-quality issue to resolve before use; this analysis stays on the validated archive. The baseline phase assignments reflect wiring observed up to about May 2026. The meter reference and implementation status above were updated for the reconnections completed on 2026-08-24; OpenEMS measurements should be used to verify the resulting live balance.

# Storage

Batteries and invertor

# Cost Analysis: Procurement and Shipment of 60kWh LFP BYD Batteries from China to Uganda

**1. Executive Summary:**

This report provides a comprehensive cost estimate for purchasing and shipping a 60kWh Lithium Iron Phosphate (LFP) battery pack manufactured by BYD from China to Uganda. The analysis encompasses the estimated purchase price in China, various shipping options and their associated costs, and the import duties and taxes applicable in Uganda. The total estimated cost is subject to considerable variation depending on factors such as the prevailing market price of batteries, the chosen shipping method (sea or air freight), and the specific import duties levied by the Ugandan authorities at the time of import. This report outlines a potential cost range to aid businesses in Uganda in their procurement planning and financial forecasting for such a significant component.

**2. Introduction:**

BYD (Build Your Dreams) stands as a prominent global manufacturer of rechargeable batteries, including Lithium-ion and LFP chemistries, with a significant presence in the electric vehicle and energy storage sectors.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="1" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">1</sup></span> The company's LFP batteries are particularly recognized for their enhanced safety features and cost-effectiveness, making them a preferred choice for a wide array of applications, from electric vehicles to stationary energy storage systems.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="1" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">1</sup></span> Given BYD's established position in the battery market, this report aims to provide a detailed cost analysis for an entity in Uganda seeking to procure a 60kWh LFP battery pack from this leading Chinese manufacturer. This analysis will delve into the primary cost drivers, including the initial purchase price of the batteries in China, the logistical expenses associated with shipping to Uganda, and the governmental levies in the form of taxes and duties imposed by both countries. Understanding these components is crucial for accurate budgeting and informed decision-making for any organization undertaking such an international procurement.

**3. Estimated Purchase Cost of 60kWh BYD LFP Batteries in China:**

The landscape of lithium-ion battery pricing in China has been characterized by a notable downward trend, primarily influenced by decreasing raw material costs and heightened competition among manufacturers.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="4" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">4</sup></span> This trend is particularly evident in the pricing of LFP batteries, which generally exhibit a more competitive cost structure compared to Nickel Cobalt Manganese (NCM) batteries.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="6" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">6</sup></span> Recent industry reports suggest that the price of LFP battery cells in China, which stood at approximately $70 per kilowatt-hour (kWh) in the near past, was anticipated to undergo substantial reductions throughout 2024, with further potential decreases projected for 2025.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="4" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">4</sup></span> Some forecasts even indicated the possibility of LFP cell prices falling below $56/kWh by mid-2024 and potentially reaching as low as $36/kWh by 2025.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="4" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">4</sup></span>

Examining online marketplaces such as Alibaba and Made-in-China reveals a variety of BYD LFP battery products listed by different suppliers, with prices varying based on factors like capacity and the specific vendor.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="16" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">16</sup></span> Given these fluctuating market conditions and supplier-specific pricing, it becomes apparent that a precise, fixed purchase price is difficult to ascertain. Instead, a more realistic approach involves considering a price range based on the available data.

Based on the per kWh price ranges identified in the research, the estimated purchase cost for a 60kWh BYD LFP battery pack in 2024 can be projected. Utilizing the lower end of the price spectrum at around $49/kWh <span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="12" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">12</sup></span> and the higher end at approximately $70/kWh <span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="4" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">4</sup></span>, the following cost range can be estimated:

**Table 1: Estimated Purchase Cost Range of 60kWh BYD LFP Batteries in China (2024)**

<table data-sourcepos="21:1-25:29" id="bkmrk-price-per-kwh-%28usd%29-" style="margin-bottom: 32px; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><tbody style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><tr data-sourcepos="21:1-21:61" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**Price per kWh (USD)**</td><td style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**Estimated Cost for 60kWh Pack (USD)**</td></tr><tr data-sourcepos="23:1-23:28" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="23:1-23:18" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">Low Estimate: 49</td><td align="left" data-sourcepos="23:20-23:26" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">2,940</td></tr><tr data-sourcepos="24:1-24:28" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="24:1-24:18" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">Mid Estimate: 60</td><td align="left" data-sourcepos="24:20-24:26" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">3,600</td></tr><tr data-sourcepos="25:1-25:29" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="25:1-25:19" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">High Estimate: 70</td><td align="left" data-sourcepos="25:21-25:27" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">4,200</td></tr></tbody></table>

This suggests that the purchase cost for a 60kWh BYD LFP battery pack could range from approximately $2,940 to $4,200 based on 2024 price levels. It is important to note that potential price reductions anticipated for 2025 could further lower these estimates.

For sourcing these batteries, platforms like Alibaba and Made-in-China serve as potential avenues, hosting numerous suppliers and distributors of BYD batteries.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="16" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">16</sup></span> Several specific companies have been identified as offering BYD battery products.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="16" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">16</sup></span> Additionally, BYD itself operates an energy storage division, which could be a direct point of contact for procurement.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="25" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">25</sup></span> While online platforms offer a broad selection of suppliers, engaging directly with BYD or their officially recognized distributors might provide enhanced assurance regarding product quality and potentially more favorable pricing terms, especially for substantial orders like a 60kWh battery pack.

**4. Shipping Cost Analysis: China to Uganda:**

Transporting a large and heavy item like a 60kWh battery pack from China to Uganda necessitates careful consideration of the available shipping methods, each with its own implications for cost and transit time. Sea freight generally emerges as the more economical option for such substantial cargo.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="37" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">37</sup></span> Within sea freight, two primary options exist: Less than Container Load (LCL) for smaller shipments that don't fill an entire container, and Full Container Load (FCL) for larger volumes.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="37" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">37</sup></span> The typical transit time for sea freight from China to Uganda ranges from 5 to 8 weeks.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="38" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">38</sup></span>

Conversely, air freight offers a significantly faster transit time, typically between 7 to 10 days for standard air freight and 2 to 4 days for express services.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="38" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">38</sup></span> However, this speed comes at a considerably higher cost compared to sea freight.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="37" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">37</sup></span>

Estimating the precise shipping costs requires considering the weight and volume of the 60kWh LFP battery pack. Research suggests that a battery pack of this capacity can vary in weight depending on the manufacturer and design, ranging from approximately 438kg for a Tesla Model 3 battery <span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="40" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">40</sup></span> to over 700kg for a Delong battery pack.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="41" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">41</sup></span>

Based on these weight figures, the estimated cost for air freight, which is typically calculated per kilogram, can be projected. Using a cost range of $7.5 to $10 per kg <span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="37" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">37</sup></span>, the air freight cost for a 60kWh battery pack could range from $3,285 (438kg \* $7.5/kg) to $7,120 (712kg \* $10/kg).

For sea freight, the cost is often determined by volume, particularly for LCL shipments, with rates ranging from $150 to $190 per cubic meter.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="37" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">37</sup></span> While the exact volume of a 60kWh battery pack was not explicitly available in the research, its substantial size likely makes an FCL shipment (using a 20-foot container) a more practical approach. The cost for an FCL 20-foot container from China to Uganda is estimated to be between $4,000 and $6,000.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="37" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">37</sup></span>

**Table 2: Estimated Shipping Cost Comparison (Sea vs. Air Freight)**

<table data-sourcepos="45:1-49:71" id="bkmrk-shipping-method-cost" style="margin-bottom: 32px; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><tbody style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><tr data-sourcepos="45:1-45:71" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**Shipping Method**</td><td style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**Cost Metric**</td><td style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**Estimated Cost (USD)**</td><td style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**Transit Time**</td></tr><tr data-sourcepos="47:1-47:77" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="47:1-47:19" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">Sea Freight (LCL)</td><td align="left" data-sourcepos="47:21-47:38" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">$150 - $190 / m³</td><td align="left" data-sourcepos="47:40-47:61" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">Requires Volume Data</td><td align="left" data-sourcepos="47:63-47:75" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">5 - 8 weeks</td></tr><tr data-sourcepos="48:1-48:74" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="48:1-48:24" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">Sea Freight (FCL 20ft)</td><td align="left" data-sourcepos="48:26-48:40" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">Per Container</td><td align="left" data-sourcepos="48:42-48:58" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">$4,000 - $6,000</td><td align="left" data-sourcepos="48:60-48:72" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">5 - 8 weeks</td></tr><tr data-sourcepos="49:1-49:71" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="49:1-49:13" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">Air Freight</td><td align="left" data-sourcepos="49:15-49:31" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">$7.5 - $10 / kg</td><td align="left" data-sourcepos="49:33-49:49" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">$3,285 - $7,120</td><td align="left" data-sourcepos="49:51-49:69" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">7 - 10 days (Std)</td></tr></tbody></table>

The selection of the shipping method will have a significant impact on the total cost. Sea freight offers substantial cost savings but necessitates a longer lead time, while air freight provides speed at a considerable premium.

Engaging a freight forwarder is a common practice for international shipments to manage the complexities of logistics and customs procedures.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="37" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">37</sup></span> These services typically involve additional fees covering documentation, customs clearance in China, and overall shipment coordination. Furthermore, it is important to anticipate potential surcharges such as fuel adjustments, port handling fees, and other miscellaneous charges that can add to the base shipping costs. Therefore, when budgeting for the shipment, an allowance for freight forwarder fees and these potential unforeseen surcharges should be included to ensure a more accurate overall cost estimation.

**5. Tax and Duty Implications:**

Navigating the tax and duty implications in both China and Uganda is a critical aspect of the overall cost analysis.

In China, the research material does not explicitly mention specific export taxes levied on batteries. While standard export procedures and minor administrative fees might be applicable, significant export duties on this commodity appear unlikely based on the provided information. Nevertheless, it is prudent to verify this with the chosen supplier or a freight forwarder based in China to preempt any unexpected charges at the point of export.

Uganda, on the other hand, has specific import duties and taxes that will apply to the incoming battery pack. Notably, Uganda recently imposed a 25% import duty on electric vehicles, hybrid vehicles, and electric motorcycles.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="48" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">48</sup></span> While batteries are not explicitly listed in this category, their fundamental role as a core component in both electric vehicles and energy storage systems strongly suggests that they are highly likely to be subject to this new import duty. Under the East Africa Customs Union (EACU) common external tariff, most finished products attract a 25% duty, further supporting the likelihood of this tariff applying to the battery pack.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="50" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">50</sup></span> This import duty is expected to be a significant contributor to the overall cost of importing the 60kWh LFP battery pack.

In addition to import duties, Uganda levies a Value Added Tax (VAT) at a standard rate of 18%.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="50" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">50</sup></span> This VAT is typically calculated on the Cost, Insurance, and Freight (CIF) value of the imported goods, which includes the purchase price, shipping costs, and the import duty itself.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="52" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">52</sup></span> Therefore, the 18% VAT will be applied on top of the combined cost of the battery, its shipment, and the 25% import duty, leading to a further increase in the total expenditure.

Other relevant taxes in Uganda include a 1.5% infrastructure tax on imports, designed to fund railway infrastructure development.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="50" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">50</sup></span> Additionally, a 15% withholding tax may be applicable to imported goods and services, although the specific applicability to batteries warrants confirmation with the Ugandan tax authorities.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="50" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">50</sup></span> While these taxes are individually lower than the import duty and VAT, they will collectively contribute to the overall tax burden associated with the import.

It is important to highlight that the Ugandan government offers potential tax exemptions and incentives for local manufacturers involved in the electric vehicle sector. Entities manufacturing electric vehicles, electric batteries, or charging equipment, and meeting specific criteria such as employing at least 80% Ugandan citizens, utilizing at least 80% locally sourced raw materials (where available), and meeting minimum investment thresholds, might be exempt from the 25% import duty and stamp duty.<span style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><sup class="superscript" data-turn-source-index="48" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; font-size: 16px !important; background-color: transparent !important;">48</sup></span> If the importing entity qualifies under these provisions, they could potentially realize significant reductions in the final cost.

To provide an estimated range for the import duties and taxes in Uganda, the following table illustrates the potential breakdown based on the low and high estimates for the purchase cost and shipping (using sea freight as the lower shipping cost):

**Table 3: Breakdown of Estimated Ugandan Import Duties and Taxes (Based on Sea Freight)**

<table data-sourcepos="73:1-80:67" id="bkmrk-item-low-estimate-%28u" style="margin-bottom: 32px; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><tbody style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><tr data-sourcepos="73:1-73:51" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**Item**</td><td style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**Low Estimate (USD)**</td><td style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**High Estimate (USD)**</td></tr><tr data-sourcepos="75:1-75:67" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="75:1-75:48" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">Estimated Value of Goods (Purchase + Shipping)</td><td align="left" data-sourcepos="75:50-75:56" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">6,940</td><td align="left" data-sourcepos="75:58-75:65" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">10,200</td></tr><tr data-sourcepos="76:1-76:56" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="76:1-76:38" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">Import Duty (25% of Estimated Value)</td><td align="left" data-sourcepos="76:40-76:46" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">1,735</td><td align="left" data-sourcepos="76:48-76:54" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">2,550</td></tr><tr data-sourcepos="77:1-77:67" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="77:1-77:46" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">VAT (18% of (Estimated Value + Import Duty))</td><td align="left" data-sourcepos="77:48-77:57" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">1,561.20</td><td align="left" data-sourcepos="77:59-77:65" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">2,295</td></tr><tr data-sourcepos="78:1-78:63" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="78:1-78:46" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">Infrastructure Tax (1.5% of Estimated Value)</td><td align="left" data-sourcepos="78:48-78:55" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">104.10</td><td align="left" data-sourcepos="78:57-78:61" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">153</td></tr><tr data-sourcepos="79:1-79:70" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="79:1-79:52" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">Potential Withholding Tax (15% of Estimated Value)</td><td align="left" data-sourcepos="79:54-79:60" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">1,041</td><td align="left" data-sourcepos="79:62-79:68" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">1,530</td></tr><tr data-sourcepos="80:1-80:67" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="80:1-80:38" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**Total Estimated Taxes and Duties**</td><td align="left" data-sourcepos="80:40-80:53" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**4,441.30**</td><td align="left" data-sourcepos="80:55-80:65" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**6,528**</td></tr></tbody></table>

*Note: The "Estimated Value of Goods" in the Low Estimate scenario uses the low purchase cost ($2,940) + the low end of the FCL sea freight cost ($4,000). The High Estimate uses the high purchase cost ($4,200) + the high end of the FCL sea freight cost ($6,000).*

**6. Total Estimated Cost and Breakdown:**

Consolidating the estimated purchase cost, shipping cost (considering both sea and air freight for a comprehensive range), and the total estimated taxes and duties, we can arrive at an overall cost projection:

**Table 4: Consolidated Total Estimated Cost Range**

<table data-sourcepos="90:1-97:71" id="bkmrk-cost-component-low-e" style="margin-bottom: 32px; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><tbody style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><tr data-sourcepos="90:1-90:61" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**Cost Component**</td><td style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**Low Estimate (USD)**</td><td style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**High Estimate (USD)**</td></tr><tr data-sourcepos="92:1-92:43" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="92:1-92:25" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">Estimated Purchase Cost</td><td align="left" data-sourcepos="92:27-92:33" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">2,940</td><td align="left" data-sourcepos="92:35-92:41" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">4,200</td></tr><tr data-sourcepos="93:1-93:57" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="93:1-93:39" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">Estimated Shipping Cost (Sea Freight)</td><td align="left" data-sourcepos="93:41-93:47" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">4,000</td><td align="left" data-sourcepos="93:49-93:55" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">6,000</td></tr><tr data-sourcepos="94:1-94:57" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="94:1-94:39" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">Estimated Shipping Cost (Air Freight)</td><td align="left" data-sourcepos="94:41-94:47" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">3,285</td><td align="left" data-sourcepos="94:49-94:55" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">7,120</td></tr><tr data-sourcepos="95:1-95:49" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="95:1-95:28" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">Estimated Taxes and Duties</td><td align="left" data-sourcepos="95:30-95:39" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">4,441.30</td><td align="left" data-sourcepos="95:41-95:47" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">6,528</td></tr><tr data-sourcepos="96:1-96:71" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="96:1-96:40" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**Total Estimated Cost (Sea Freight)**</td><td align="left" data-sourcepos="96:42-96:56" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**11,381.30**</td><td align="left" data-sourcepos="96:58-96:69" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**16,728**</td></tr><tr data-sourcepos="97:1-97:71" style="font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"><td align="left" data-sourcepos="97:1-97:40" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**Total Estimated Cost (Air Freight)**</td><td align="left" data-sourcepos="97:42-97:56" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**10,666.30**</td><td align="left" data-sourcepos="97:58-97:69" style="border: 1px solid; font-family: Google Sans Text, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;">**17,848**</td></tr></tbody></table>

The total estimated cost for purchasing and shipping a 60kWh LFP BYD battery pack from China to Uganda could range significantly, potentially from approximately $10,666.30 (low purchase cost + low air freight + low taxes/duties) to $17,848 (high purchase cost + high air freight + high taxes/duties). If sea freight is chosen, the range would be approximately $11,381.30 to $16,728.

**7. Key Considerations and Recommendations:**

For any entity in Uganda looking to undertake this procurement, several key considerations and recommendations should be taken into account:

- **Supplier Negotiation:** Actively engage in negotiations with potential battery suppliers in China to secure the most competitive purchase price, especially when dealing with larger order volumes.
- **Incoterms:** Clearly define and agree upon the Incoterms with the chosen supplier. These terms dictate the responsibilities and costs associated with transportation and delivery, including who bears the risk at different stages of the shipping process.
- **Shipping Insurance:** Secure adequate shipping insurance to protect against potential damage or loss of the valuable cargo during its transit from China to Uganda.
- **Quality Control:** Implement stringent quality control measures in China, preferably through on-site inspections before shipment, to ensure the battery pack meets the required technical specifications and quality standards.
- **Customs Clearance in Uganda:** Partner with a reputable and experienced customs broker in Uganda. Their expertise will be invaluable in navigating the import clearance procedures, ensuring compliance with all Ugandan regulations, and potentially expediting the process.
- **Verification of Import Duties and Taxes:** It is strongly recommended to directly contact the Uganda Revenue Authority (URA) or consult with a qualified tax professional in Uganda. This step is crucial to obtain the most up-to-date and accurate information regarding import duties, VAT rates, and the applicability of any potential exemptions for battery imports. The information provided in this report is based on currently available data but is subject to change.
- **Exploring Local Suppliers:** While the focus of this report is on importing from China, it might be worthwhile to briefly explore the possibility of sourcing similar batteries from local suppliers within Uganda or the broader East African region. However, the availability and cost-effectiveness of BYD LFP batteries through these channels may be limited.
- **Long-Term Cost Analysis:** When evaluating the overall cost, consider the long-term benefits associated with LFP batteries, such as their extended lifespan, high cycle life, and potentially lower maintenance requirements compared to other battery chemistries. These factors can contribute to a more favorable total cost of ownership over the operational life of the battery pack.

By carefully considering these recommendations and conducting thorough due diligence, the procuring entity in Uganda can better navigate the complexities and costs associated with importing a 60kWh LFP BYD battery pack from China.

# Battery as a service Provider

SLS energy based in Rwanda

Cost: USD 4.40-6.48 kwh of system capacity available per month. Also depends on the duration of the lease.

# SRNE

See product catalog here: [https://www.srnesolar.com/](https://www.srnesolar.com/)

They have a factory showroom in [Naguru. ](https://maps.app.goo.gl/nt9UFgwLDf7DBKWD9)

Pricing from the factory showroom below. Full price list here:[Uganda SRNE item price list.pdf](https://bookstack.nearlyfreeenergy.com/attachments/58)

- 5.12 KW battery - 3.22m UGX
- 6kw inverter - 3.74m UGX
- 10kw inverter - 4.611m UGX
- 12kw inverter - 7.673m UGX

Quote from a thirrdparty local supplier is attached here. [Quote-105 (1).pdf](https://bookstack.nearlyfreeenergy.com/attachments/55).

Datasheet here: [SRNE\_HESP series\_EU\_48V\_3.6\_6kW\_230V\_Single-Phase\_Hybrid\_Solar Storage Inverter\_Datasheet\_V1.2\[20250618\] (1).pdf](https://bookstack.nearlyfreeenergy.com/attachments/56)

Modbus Protocol: [SRNE Solar Charge Inverter MODBUS Protocol1.96 (1).pdf](https://bookstack.nearlyfreeenergy.com/attachments/57)

# FENECon - Germany

They shared their quote here [Fenecon quote.pdf](https://bookstack.nearlyfreeenergy.com/attachments/59). It's a detailed plug and play system at about 10k USD for 20kWh.

# Solei Power - Uganda

[https://www.soleilpower.ug/](https://www.soleilpower.ug/)

They are offering LFP batteries (locally manufactured) with BMS.

They quoted:

<div id="bkmrk-%241350-after-a-10%25-di"><div class="message-container is-dm"><div class="message"><div class="message-main negate-redacted-region"><div class="message-click-boundary"><div class="message-children"><main><div class="message-contents-container hasText"><div class="message-contents MessageContent-module__contents"><div class="message-text-container" data-sentry-component="MessageTextComponent" data-sentry-source-file="MessageText.tsx"><div class="message-text" dir="auto" title=""><div class="preserving-whitespace" data-sentry-component="renderText" data-sentry-source-file="MessageText.tsx">$1350 after a 10% discount for 5.12 kWh </div><div class="preserving-whitespace" data-sentry-component="renderText" data-sentry-source-file="MessageText.tsx">If we want to do 25kwh, they can supply with rack and parallel/terminal cables for $6630. That's about 15% off</div></div></div></div></div></main></div></div></div></div></div></div><div id="bkmrk-"><div class="message-container is-dm"><div class="message"><div class="message-main negate-redacted-region"><div class="message-click-boundary"><div class="message-children"><div class="BrandMessageFlyover-module__flyover BrandMessageFlyover-module__disableReactions">- <button class=""><svg data-sentry-component="AssetComponent" data-sentry-element="Asset" data-sentry-source-file="with-assets.tsx" fill="none" height="20" viewbox="0 0 20 20" width="20" xmlns="http://www.w3.org/2000/svg"><path d="M15.8333 15.8337V12.5003C15.8333 11.8059 15.5903 11.2156 15.1042 10.7295C14.6181 10.2434 14.0278 10.0003 13.3333 10.0003H5.6875L8.6875 13.0003L7.5 14.167L2.5 9.16699L7.5 4.16699L8.6875 5.33366L5.6875 8.33366H13.3333C14.4861 8.33366 15.4688 8.73991 16.2812 9.55241C17.0938 10.3649 17.5 11.3475 17.5 12.5003V15.8337H15.8333Z" fill="currentColor"></path></svg></button>
- <button class=""><svg data-sentry-component="AssetComponent" data-sentry-element="Asset" data-sentry-source-file="with-assets.tsx" fill="none" height="20" viewbox="0 0 20 20" width="20" xmlns="http://www.w3.org/2000/svg"><path d="M12.9167 9.16699C13.2639 9.16699 13.559 9.04546 13.8021 8.80241C14.0451 8.55935 14.1667 8.26421 14.1667 7.91699C14.1667 7.56977 14.0451 7.27463 13.8021 7.03158C13.559 6.78852 13.2639 6.66699 12.9167 6.66699C12.5694 6.66699 12.2743 6.78852 12.0313 7.03158C11.7882 7.27463 11.6667 7.56977 11.6667 7.91699C11.6667 8.26421 11.7882 8.55935 12.0313 8.80241C12.2743 9.04546 12.5694 9.16699 12.9167 9.16699ZM7.08334 9.16699C7.43056 9.16699 7.7257 9.04546 7.96875 8.80241C8.21181 8.55935 8.33334 8.26421 8.33334 7.91699C8.33334 7.56977 8.21181 7.27463 7.96875 7.03158C7.7257 6.78852 7.43056 6.66699 7.08334 6.66699C6.73612 6.66699 6.44098 6.78852 6.19792 7.03158C5.95487 7.27463 5.83334 7.56977 5.83334 7.91699C5.83334 8.26421 5.95487 8.55935 6.19792 8.80241C6.44098 9.04546 6.73612 9.16699 7.08334 9.16699ZM10 14.5837C10.9444 14.5837 11.8021 14.3163 12.5729 13.7816C13.3438 13.2469 13.9028 12.542 14.25 11.667H5.75001C6.09723 12.542 6.65625 13.2469 7.42709 13.7816C8.19792 14.3163 9.05556 14.5837 10 14.5837ZM10 18.3337C8.84723 18.3337 7.76389 18.1149 6.75 17.6774C5.73612 17.2399 4.85417 16.6462 4.10417 15.8962C3.35417 15.1462 2.76042 14.2642 2.32292 13.2503C1.88542 12.2364 1.66667 11.1531 1.66667 10.0003C1.66667 8.84755 1.88542 7.76421 2.32292 6.75033C2.76042 5.73644 3.35417 4.85449 4.10417 4.10449C4.85417 3.35449 5.73612 2.76074 6.75 2.32324C7.76389 1.88574 8.84723 1.66699 10 1.66699C11.1528 1.66699 12.2361 1.88574 13.25 2.32324C14.2639 2.76074 15.1458 3.35449 15.8958 4.10449C16.6458 4.85449 17.2396 5.73644 17.6771 6.75033C18.1146 7.76421 18.3333 8.84755 18.3333 10.0003C18.3333 11.1531 18.1146 12.2364 17.6771 13.2503C17.2396 14.2642 16.6458 15.1462 15.8958 15.8962C15.1458 16.6462 14.2639 17.2399 13.25 17.6774C12.2361 18.1149 11.1528 18.3337 10 18.3337ZM10 16.667C11.8611 16.667 13.4375 16.0212 14.7292 14.7295C16.0208 13.4378 16.6667 11.8614 16.6667 10.0003C16.6667 8.13921 16.0208 6.56283 14.7292 5.27116C13.4375 3.97949 11.8611 3.33366 10 3.33366C8.13889 3.33366 6.56251 3.97949 5.27084 5.27116C3.97917 6.56283 3.33334 8.13921 3.33334 10.0003C3.33334 11.8614 3.97917 13.4378 5.27084 14.7295C6.56251 16.0212 8.13889 16.667 10 16.667Z" fill="currentColor"></path></svg></button>

</div></div></div></div></div></div></div>

# Billing

# Billing and Payment System evalutation

<table border="1" id="bkmrk-attribute-cost-%28mone" style="border-collapse: collapse; width: 100%; height: 266.375px;"><colgroup><col style="width: 16.6667%;"></col><col style="width: 16.6667%;"></col><col style="width: 16.6667%;"></col><col style="width: 16.6667%;"></col><col style="width: 16.6667%;"></col><col style="width: 16.6667%;"></col></colgroup><tbody><tr style="height: 46.5938px;"><td style="height: 46.5938px;">Attribute</td><td style="height: 46.5938px;">Cost (money)</td><td style="height: 46.5938px;">Interoperability</td><td style="height: 46.5938px;">long term relationship</td><td style="height: 46.5938px;">Deployment Readiness</td><td style="height: 46.5938px;">Quality   
</td></tr><tr style="height: 35.3984px;"><td style="height: 35.3984px;"><span style="color: rgb(22, 145, 121);">**[Pesapal](https://bookstack.nearlyfreeenergy.com/books/product/page/pesapal)** </span>  
</td><td style="height: 35.3984px;"><span style="color: rgb(22, 145, 121);">**1**</span></td><td style="height: 35.3984px;"><span style="color: rgb(22, 145, 121);">**3**</span></td><td style="height: 35.3984px;"><span style="color: rgb(22, 145, 121);">**5**</span></td><td style="height: 35.3984px;"><span style="color: rgb(22, 145, 121);">**5**</span></td><td style="height: 35.3984px;"><span style="color: rgb(22, 145, 121);">**5**</span></td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Jumia Pay</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Pegasus   
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td></tr><tr style="height: 35.3984px;"><td style="height: 35.3984px;">[Kitegateway](https://kitegateway.com/home/index.html#product)</td><td style="height: 35.3984px;">3</td><td style="height: 35.3984px;">3</td><td style="height: 35.3984px;">5</td><td style="height: 35.3984px;">3</td><td style="height: 35.3984px;">3</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Stripe Atlas</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Flutterwave</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">Stanbic</td><td style="height: 29.7969px;">3</td><td style="height: 29.7969px;">3</td><td style="height: 29.7969px;">5</td><td style="height: 29.7969px;">3</td><td style="height: 29.7969px;">3</td></tr></tbody></table>

# Pesapal

<div class="elementToProof" id="bkmrk-in-brief%3A-pesapal-is" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;">In Brief: Pesapal is a Payment Service Provider that enables various forms of Payment options for business in one platform. Through our Online and Point of Sale Payments services, we ensure customers have a variety of options, and your team can monitor all transactions coming through in one web-based merchant dashboard.</div><div class="elementToProof" id="bkmrk-" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;">  
</div><div class="elementToProof" id="bkmrk-online-products%3A" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;">**<u style="max-width: 100%;">ONLINE PRODUCTS:</u>**</div><div class="elementToProof" id="bkmrk--1" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;">**<u style="max-width: 100%;">  
</u>**</div><div class="elementToProof" id="bkmrk-%C2%A0payment-link" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;">**<u style="max-width: 100%;"> Payment Link</u>**</div><div class="elementToProof" id="bkmrk--2" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;">**<u style="max-width: 100%;">  
</u>**</div><div class="elementToProof" id="bkmrk-%C2%A0we-provide-a-person" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;"> We provide a personalised payments page link that enables your clients to pay you both on and off the website. It accepts Visa, Mastercard, AMEX and mobile money payments. For example, [ https://payments.pesapal.com/wildwaterslodge](https://payments.pesapal.com/wildwaterslodge "https://payments.pesapal.com/wildwaterslodge")</div><div class="elementToProof" id="bkmrk--3" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;">**<u style="max-width: 100%;">  
</u>**</div><div class="elementToProof" id="bkmrk--4" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;">  
</div><div class="elementToProof" id="bkmrk-benefits%3A" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;"><u style="max-width: 100%;">Benefits:</u></div>- <div style="margin: 0px; max-width: 100%;">Saves Time &amp; Cost: Rids off the time and resources of having to register orders &amp; bookings manually.</div>
- <div style="margin: 0px; max-width: 100%;">Drive Sales 24/7: Push for sales all day as long as you are open without fear of overbookings</div>
- <div style="margin: 0px; max-width: 100%;">Reduce risk on Fraud: All payments are posted in real-time reducing risk of handling payments manually</div>
- <div style="margin: 0px; max-width: 100%;"> You can run promotions on social media pages using links that will direct guests to place direct bookings to any property as well as to complete payment. i.e.[https://payments.pesapal.com/wildwaterslodge](https://payments.pesapal.com/wildwaterslodge "https://payments.pesapal.com/wildwaterslodge")</div>

<div class="elementToProof" id="bkmrk-find-below-examples-" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;">Find Below examples of some of the properties and the links that we have Integrated the online booking engine.</div>- <div style="margin: 0px; max-width: 100%;">Arcadia Lodges -<span style="background-color: rgb(255, 255, 255); max-width: 100%;">[https://arcadialodges.reserveport.com/](https://arcadialodges.reserveport.com/ "https://arcadialodges.reserveport.com/")</span></div>
- <div style="margin: 0px; max-width: 100%;">Imperial Hotels -<span style="background-color: rgb(255, 255, 255); max-width: 100%;">[https://imperialhotels.reserveport.com/](https://imperialhotels.reserveport.com/ "https://imperialhotels.reserveport.com/")</span></div>
- <div style="margin: 0px; max-width: 100%;">BMK House - [ https://bmkhouse.reserveport.com/](https://bmkhouse.reserveport.com/ "https://bmkhouse.reserveport.com/")</div>

<div class="elementToProof" id="bkmrk--5" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;">  
</div><div class="elementToProof" id="bkmrk-b%29point-of-sale-mach" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;">**B)<u style="max-width: 100%;">Point of sale machine</u>**</div><div class="elementToProof" id="bkmrk--6" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 16px; color: rgb(0, 0, 0); max-width: 100%;"><span style="background-color: rgb(255, 255, 255); max-width: 100%;">![cid:b75f8c5e-18fd-4b37-bd97-65a8b3c42067](https://nextcloud.nearlyfreeenergy.com/apps/mail/api/messages/255/attachment/2)</span></div><div class="elementToProof" id="bkmrk--7" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;"><u style="max-width: 100%;">  
</u></div><div class="elementToProof" id="bkmrk-distinct-features" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;"><u style="max-width: 100%;">Distinct features</u></div>- <div style="margin: 0px; max-width: 100%;">Fast set up and training in 24 hours </div>
- <div style="margin: 0px; max-width: 100%;">Accept VISA , MasterCard &amp; Mobile Money payments</div>
- <div style="margin: 0px; max-width: 100%;">Process MTN Mobile Money payments</div>
- <div style="margin: 0px; max-width: 100%;">Customer receives physical receipts for Mobile Money and card payments, you also retain the merchant copies to help in reconciliations.</div>
- <div style="margin: 0px; max-width: 100%;">Stable connection with both 4G + Wi-Fi</div>
- <div style="margin: 0px; max-width: 100%;">Virtual Cards from Booking.com &amp; Expedia can be charged </div>
- <div style="margin: 0px; max-width: 100%;">Tap and Go feature</div>
- <div style="margin: 0px; max-width: 100%;">Next day settlement</div>
- <div style="margin: 0px; max-width: 100%;">Settlement to any Bank in Uganda</div>
- <div style="margin: 0px; max-width: 100%;">Very competitive transaction fees .</div>
- <div style="margin: 0px; max-width: 100%;">Access real-time reports</div>
- <div style="margin: 0px; max-width: 100%;">Branded receipt with your company logo</div>
- <div style="margin: 0px; max-width: 100%;">Integrate with any 3rd party POS system</div>
- <div style="margin: 0px; max-width: 100%;">Mitigate fraud and human error during reconciliation</div>

<div class="elementToProof" id="bkmrk-c%29%C2%A0payment-link" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;">**C)<u style="max-width: 100%;"> Payment Link</u>**</div><div class="elementToProof" id="bkmrk-%C2%A0we-provide-a-person-1" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;"> We provide a personalised payments page link that enables your clients to pay you both on and off the website. It accepts Visa, Mastercard, AMEX and mobile money payments. For example, [ https://payments.pesapal.com/wildwaterslodge](https://payments.pesapal.com/wildwaterslodge "https://payments.pesapal.com/wildwaterslodge")</div><div class="elementToProof" id="bkmrk--8" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;">  
</div><div class="elementToProof" id="bkmrk-rates-and-costs" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;">**<u style="max-width: 100%;">Rates and costs</u>**</div>- <div style="margin: 0px; max-width: 100%;">Card rate per transaction- 2.5%</div>
- <div style="margin: 0px; max-width: 100%;">mobile money per transaction is 2%</div>
- <div style="margin: 0px; max-width: 100%;">Online Rate per transaction- 3.5%</div>
- <div style="margin: 0px; max-width: 100%;">Payment page set up-No cost</div><div style="margin: 0px; max-width: 100%;">  
    </div>

<div class="elementToProof" id="bkmrk-documents-required-t" style="text-align: left; text-indent: 0px; background-color: rgb(255, 255, 255); margin: 0px; font-family: Aptos, 'Aptos_EmbeddedFont', 'Aptos_MSFontService', Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); max-width: 100%;">**<u style="max-width: 100%;">Documents required to be submitted</u>**</div>- <div style="margin: 0px; max-width: 100%;">Certificate of incorporation</div>
- <div style="margin: 0px; max-width: 100%;">Form 20 </div>
- <div style="margin: 0px; max-width: 100%;">Form 1</div>
- <div style="margin: 0px; max-width: 100%;">TIN certificate</div>
- <div style="margin: 0px; max-width: 100%;">IDs for the directors as per the form 20</div>
- <div style="margin: 0px; max-width: 100%;">Cancelled cheque leaf or Bank statement/ Bank letter confirming bank details</div>
- <div style="margin: 0px; max-width: 100%;">Completed signup form [Pesapal Sign Up Form new.pdf](https://bookstack.nearlyfreeenergy.com/attachments/3)</div>

<span style="text-decoration: underline;">**Questions from Aaron**</span>

**Rates and Costs**: In your current workflow, are these costs paid by customers (transparently) or charged to the merchant (hidden from the customer)? I pay my Yaka bill with MTN mobile money and when I pay for a token of 200k UGX, I am charged a 4150 UGX. I would like an approach where fees are transparent to the customer and not hidden. <span style="color: rgb(12, 100, 192); max-width: 100%;">Customers are charged for every transaction they make see attached tariff [Tarrif .png](https://bookstack.nearlyfreeenergy.com/attachments/2). In addition, merchant is charged commission of 3.5% per transaction</span>

**Payment links/Page**: There's two options I would like to discuss here. There examples you shared for the lodges are one option. I would like to know if I can have the option of NFE appearing among the Pay Utility options on [ this page](https://ugpayonline.pesapal.com/)<span style="color: rgb(0, 0, 0); max-width: 100%;">. Is that option available to us?</span><span style="color: rgb(12, 100, 192); max-width: 100%;"> This is not an available option, we can engage our developers on this.</span>

**Timelines for payment settlement**: I would like to understand what your current average timelines are for settling funds to Merchants and Customers in the following cases

\- Depositing funds on Merchant accounts after completion of a customer transaction. Let me know if these differ depending on the payment method the customer uses. Understanding these will help my team plan what our cashflow expectations if we decide to work with Pesapal. <span style="color: rgb(12, 100, 192); max-width: 100%;"> Settlement to merchant accounts takes 24hrs,we have developed this to have real time settlements to any bank or mobile money</span>

\- Refunding customers for transactions done in error or overpayment. How long before a customer receives their fund on their orginal form of payment when NFE initiates are refund through PesaPal. <span style="color: rgb(12, 100, 192); max-width: 100%;">Reversals to customers take effect from the time we are notified</span>

**Documents required to be submitted:** We are able to provide all these documents. I think you forgot to attach the sign-up form. <span style="color: rgb(12, 100, 192); max-width: 100%;">See attached the sign up form</span>

Lastly, in full transparency, this decision for our payments partner is still pending. We are currently evaluating other providers like Jumia Pay, Pegasus and setting up direct integrations with Telcos and Banks. We are aiming to make a decision on this by end of this week.<span style="color: rgb(12, 100, 192); max-width: 100%;"> Can we run a test account as you evaluate on the providers, this will give us the real feel.</span>

# Microgrid Capability Map

Microgrid Capabilities

This diagram shows the distinct capabilities the microgrid will have and the level of freedom each capabilities for each capability's current implementation offers the community the microgrid is serving. The diagram also show Aaron's understanding of the level of risk to the model associated with each capability given what we know about it. The capabilities without a risk profile assigned are not targeted to go live yet.

<div drawio-diagram="87"><img src="https://bookstack.nearlyfreeenergy.com/uploads/images/drawio/2026-04/drawing-4-1777327212.png" alt=""/></div>

Our capabilities are currently evolving across 3 generations. See [our roadmap](https://bookstack.nearlyfreeenergy.com/books/team/page/roadmap) for progress updates.

### Generation 1 

- Hardware and or software propritary but accessible to small microgrid developers
- Hardware needs to be sourced from out of country
- Cost of hardware purchase is high and so is cost of repair
- Software licenses may be prohibitively expensive for small developers/communities because they are meant to target larger scale buyers

### Generation 2 

- Hardware still proprietary but can be locally sourced
- The software is open source and can be run by small developers or several SaaS providers giving developers options
- Cost of hardware purchase is comparatively lower than Gen 1 and cost of repair is similar to Gen 1 since hardware is still proprietary

### Generation 3 

- Hardware is open, can be assembled in country or locally sourced
- The software is open source and so is the hardware firmware
- Cost of purchase and repair of hardware is optimal

# Microgrids 101

[This page](https://lf-energy.atlassian.net/wiki/spaces/HYP/pages/260341781/Microgrid+introduction) and [Wikipedia](https://en.wikipedia.org/wiki/Microgrid#:~:text=Electropedia%20defines%20a%20microgrid%20as,voltage%20up%20to%2035%20kV.) go into great detail to describe the concept of a microgrid. I would like to expand on that. During one of the weekly LF Energy Hyphae community checkin calls. When I explained that the initial phase for NFE's pilot microgrid will only include sub-metering a handful of homes. My colleague commented that "Oh, so it won't really be a microgrid yet". That statement stuck with me because I infant think it would be a microgrid. Which brings us to the question I would like to address in this article. What do I mean when I say "microgrid".

### Why definitions matter

Definitions generally matter because they help us communicate more clearly about the problem and how we are solving it. If we can agree on what we when when we say "microgrid" or "battery" then it makes it simpler to have conversations about which use-cases make sense for Hyphae's autonomous microgrid idea to address.

### First principles 

The term *microgrid* is a compound term. It consists of two terms *micro* and *grid*. I will start with the assertion that a microgrid is first a *grid*. If we are agreed there (pun not intended), then let's move on to define what we mean by *grid*.

A grid, in it's most primitive form, is really a set of at least two energy assets, connected, usually by physical energy conducting medium like a wire for a purpose. Let's look at the picture below.

<div drawio-diagram="12"><img src="https://bookstack.nearlyfreeenergy.com/uploads/images/drawio/2025-05/drawing-4-1747946609.png" alt=""/></div>

The energy asset on the left (battery) is producing energy and the asset to the right is consuming energy. The two assets have been connected for a purpose and I think that's actually an a very simple example of a grid. Now this grid can include more than 2 assets and in the real world, there's often 100s of assets connected to a grid but for the sake of defining the term, I think this example will serve us well.

If you are still with me, let's move on to the preceding term, the *micro* term. This term adds a layer of meaning to the Grid term. I propose that the distiction between Micro and Macro is really about scope of monitoring and steering for the "owner(s)" of the grid. If the scope is considered small by the owner and exists within the context of a larger grid, then we have ourselves a *microgrid*.

### Energy Assets 

These exist in various forms but here's an oversimplified list [Energy\_Asset\_Taxonomy.csv](https://bookstack.nearlyfreeenergy.com/attachments/4). I share it here to example one's imagination on the kind of things that can exist on a microgrid.

##### **Supply-Side Assets (Energy Producers)**

These generate or inject energy into the system.

<table id="bkmrk-subtype-example-asse"><thead><tr><th>**Subtype**

</th><th>**Example Assets**

</th><th>**Notes**

</th></tr></thead><tbody><tr><td>Renewable Generators

</td><td>Solar panels, wind turbines

</td><td>Often variable in output

</td></tr><tr><td>Non-renewable Generators

</td><td>Diesel gensets, gas turbines

</td><td>Firm or dispatchable supply

</td></tr><tr><td>Co-generation Units

</td><td>CHP systems

</td><td>Produce electricity + heat

</td></tr></tbody></table>

##### **Demand-Side Assets (Energy Consumers)**

These draw energy from the system.

<table id="bkmrk-subtype-example-asse-1"><thead><tr><th>**Subtype**

</th><th>**Example Assets**

</th><th>**Notes**

</th></tr></thead><tbody><tr><td>Residential Loads

</td><td>Lighting, HVAC, appliances

</td><td>Often flexible for DR programs

</td></tr><tr><td>Industrial Loads

</td><td>Motors, manufacturing equipment

</td><td>Usually larger and more steady

</td></tr><tr><td>Electric Vehicles

</td><td>While charging

</td><td>Can also act as supply (see V2G)

</td></tr></tbody></table>

##### **Storage Assets (Bidirectional)**

These can both store (consume) and release (supply) energy.

<table id="bkmrk-subtype-example-asse-2"><thead><tr><th>**Subtype**

</th><th>**Example Assets**

</th><th>**Notes**

</th></tr></thead><tbody><tr><td>Battery Storage

</td><td>Lithium-ion, lead-acid

</td><td>Fast response, scalable

</td></tr><tr><td>Mechanical Storage

</td><td>Flywheels, pumped hydro

</td><td>Used in larger systems

</td></tr><tr><td>Thermal Storage

</td><td>Ice storage, molten salt

</td><td>Stores heat, not electricity

</td></tr></tbody></table>

##### **Hybrid/Prosumer Assets**

Assets that both consume and produce energy as part of normal operation.

<table id="bkmrk-subtype-example-asse-3"><thead><tr><th>**Subtype**

</th><th>**Example Assets**

</th><th>**Notes**

</th></tr></thead><tbody><tr><td>Solar + Battery Systems

</td><td>Rooftop PV with integrated battery

</td><td>Common in homes &amp; businesses

</td></tr><tr><td>EVs with V2G

</td><td>Electric Vehicles (bi-directional)

</td><td>Vehicle-to-grid capable

</td></tr><tr><td>Smart Appliances

</td><td>Can adjust operation dynamically

</td><td>May support DR/load shifting

</td></tr></tbody></table>

##### **Monitoring &amp; Steering Assets (Support Infrastructure)**

These don’t directly consume or produce energy, but enable management.

<table id="bkmrk-subtype-example-asse-4" style="width: 76.9126%;"><thead><tr><th style="width: 21.5302%;">**Subtype**

</th><th style="width: 43.4164%;">**Example Assets**

</th><th style="width: 35.0534%;">**Notes**

</th></tr></thead><tbody><tr><td style="width: 21.5302%;">Smart Meters

</td><td style="width: 43.4164%;">Energy meters with comms

</td><td style="width: 35.0534%;">Enable billing, monitoring

</td></tr><tr><td style="width: 21.5302%;">IoT Sensors

</td><td style="width: 43.4164%;">Voltage, temperature, fault sensors

</td><td style="width: 35.0534%;">Support system diagnostics

</td></tr><tr><td style="width: 21.5302%;">Controllers/EMS

</td><td style="width: 43.4164%;">Inverters, EMS, SCADA systems

</td><td style="width: 35.0534%;">Coordinate and control flow

</td></tr></tbody></table>

### Monitoring and Steering the microgrid

This capabilities represent what the purpose for a microgrid can be. In the example of NFE's first phase of microgrid deployment. The purpose can be thought of as 3 part;

- for the owner (of the microgrid) to monitor energy consumptions patterns to inform additions of supply side assets like batteries in future so that energy can be more reliable for the community
- for the owner and consumers to bulk purchase electricity there by making it more affordable.
- for the owner and consumers to evolve the their experience of transacting on the grid. Prepaid vs postpaid vs credits to consumers.

The point here being that these capabilities of monitoring and steering (the assets) on the grid are a means to achieve a variety of purposes for the grid owner and other grid stakeholders.

### The Autonomous Microgrid 

This is what I think can be the vision for project [Hyphae](https://lfenergy.org/projects/hyphae/), to be able to simply define a start and end state for grid attributes we care about and have Hyphae monitor and steer the grid to the end state. For example, the end state could be 90% reliability for all demand side assets on the grid. Hyphae can then make sure that energy is being drawn or stored or cut off from some assets so that we can maintain a reliability of 90%.

That's what I imagine an autonomous microgrid should be capable of doing. There may be aspects of grid operations that will require manual human intervention like replacing a malfunctioning asset or making a payment for a bill but the more you think about it, the more you recorgnize that almost every aspect has potential to be automated to make the grid completely autonomous.

### Levels of Microgrid Autonomy 

I am thinking about how we can borrow from [the 6 levels for Self driving cars ](https://www.sae.org/standards/content/j3016_201806/)to define levels for Microgrids..

TBD

# OpenEMS

# New Page



# Getting Started

# ZeroTier Remote Access Guide

This guide explains how to connect to the NFE Raspberry Pi from anywhere in the world using ZeroTier. It covers both SSH access and troubleshooting common issues.

---

## Table of Contents
1. [Prerequisites](#prerequisites)
2. [Network Information](#network-information)
3. [Installing ZeroTier on Your Computer](#installing-zerotier-on-your-computer)
4. [Joining the Network](#joining-the-network)
5. [SSH Access to Raspberry Pi](#ssh-access-to-raspberry-pi)
6. [Troubleshooting](#troubleshooting)
7. [Setting Up ZeroTier on a New Raspberry Pi](#setting-up-zerotier-on-a-new-raspberry-pi)

---

## Prerequisites

Before starting, you need:
- A Mac or Windows laptop
- A ZeroTier account (free at https://my.zerotier.com)
- ZeroTier One installed on your computer
- Network authorization from the network administrator

---

## Network Information

**Network ID:** `2873fd00f2d70904`
**Network Name:** `my-first-network`
**Raspberry Pi ZeroTier IP:** `10.135.127.86`
**Raspberry Pi Username:** `nfetestpi2`

---

## Installing ZeroTier on Your Computer

### Mac:
1. Download ZeroTier One: https://www.zerotier.com/download/
2. Install it normally
3. After installation, the ZeroTier icon will appear in the top-right menu bar

### Windows:
1. Download ZeroTier from https://www.zerotier.com/download/
2. Install and launch it
3. ZeroTier icon will appear in the system tray

---

## Joining the Network

### Method 1: Using the ZeroTier Menu (Mac - Recommended)

1. Click the ZeroTier icon in your menu bar
2. You'll see "My Address:" with your device ID
3. Click on the network ID `2873fd00f2d70904` if it's already listed
4. Or select "Join New Network..." and enter: `2873fd00f2d70904`
5. The status will show "REQUESTING_CONFIGURATION"

### Method 2: Using Command Line

Mac/Linux:
```bash
sudo zerotier-cli join 2873fd00f2d70904
```

Windows (run as Administrator):
```cmd
zerotier-cli join 2873fd00f2d70904
```

### Authorization

After joining, you need to be authorized:

1. Contact the network administrator
2. Provide them with your device's MAC address or Device ID
3. They will authorize your device at https://my.zerotier.com
4. Once authorized, your device will receive an IP address like `10.135.127.xxx`

### Verify Connection

Mac/Linux:
```bash
sudo zerotier-cli listnetworks
```

You should see:
```
200 listnetworks 2873fd00f2d70904 my-first-network ... OK PRIVATE ... 10.135.127.xxx/24
```

The status should show **OK** and you should have an IP address assigned.

---

## SSH Access to Raspberry Pi

Once connected to the ZeroTier network, you can SSH to the Raspberry Pi:

```bash
ssh nfetestpi2@10.135.127.86
```

Enter the password when prompted.

**Note:** If you get a password prompt but it keeps failing, try using the `-v` flag for verbose output:
```bash
ssh -v nfetestpi2@10.135.127.86
```

### Optional: Set Up SSH Keys (Recommended)

To avoid entering passwords every time:

1. Generate SSH key on your computer (if you don't have one):
```bash
ssh-keygen -t ed25519 -C "your-email@example.com"
```

2. Copy your public key:
```bash
cat ~/.ssh/id_ed25519.pub
```

3. Add it to the Pi's authorized keys (via SSH or Raspberry Pi Connect):
```bash
mkdir -p ~/.ssh
nano ~/.ssh/authorized_keys
# Paste your public key, save and exit

# Set correct permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
```

4. Now you can SSH without a password:
```bash
ssh nfetestpi2@10.135.127.86
```

---

## Troubleshooting

### Issue: ZeroTier shows "REQUESTING_CONFIGURATION"

**Cause:** Your device hasn't been authorized on the network yet.

**Solution:**
1. Go to https://my.zerotier.com
2. Log in and navigate to network `2873fd00f2d70904`
3. Click "Member Devices" tab
4. Find your device and check the "Auth" checkbox

### Issue: ZeroTier shows "OFFLINE"

**Cause:** ZeroTier service isn't running properly.

**Solution for Mac:**
```bash
# Restart ZeroTier service
sudo launchctl unload /Library/LaunchDaemons/com.zerotier.one.plist
sudo launchctl load /Library/LaunchDaemons/com.zerotier.one.plist

# Verify it's online
sudo zerotier-cli info
```

You should see:
```
200 info <device-id> 1.16.0 ONLINE
```

**Solution for Windows:**
- Restart the ZeroTier service from Services (services.msc)
- Or restart the ZeroTier One application

### Issue: Can't ping or SSH to Raspberry Pi

**Symptoms:**
```bash
ping 10.135.127.86
# Shows: "No route to host" or "Request timeout"
```

**Solutions:**

1. **Check if ZeroTier is running on both devices:**
```bash
sudo zerotier-cli info
# Should show: ONLINE
```

2. **Verify both devices are on the same network:**
```bash
sudo zerotier-cli listnetworks
# Both should show network 2873fd00f2d70904 with status OK
```

3. **Try changing WiFi networks:**
Sometimes the initial WiFi network blocks ZeroTier's peer-to-peer connections. Try connecting to a different WiFi network or mobile hotspot.

4. **Check for RELAY connection:**
```bash
sudo zerotier-cli peers
```
If the Pi shows as "RELAY" instead of "DIRECT", there's a NAT traversal issue. Try:
- Restarting ZeroTier on both devices
- Leaving and rejoining the network
- Changing WiFi networks

5. **Restart ZeroTier on both devices:**

Mac:
```bash
sudo launchctl unload /Library/LaunchDaemons/com.zerotier.one.plist
sudo launchctl load /Library/LaunchDaemons/com.zerotier.one.plist
```

Raspberry Pi (via Raspberry Pi Connect):
```bash
sudo systemctl restart zerotier-one
```

6. **Leave old networks:**
If you have multiple networks joined, leave unused ones:
```bash
# List networks
sudo zerotier-cli listnetworks

# Leave old network
sudo zerotier-cli leave <old-network-id>
```

### Issue: SSH password keeps failing

**Solutions:**

1. Try verbose SSH to see what's happening:
```bash
ssh -v nfetestpi2@10.135.127.86
```

2. Make sure you're using the correct username (`nfetestpi2`, not `pi`)

3. Set up SSH keys instead (see SSH Keys section above)

---

## Setting Up ZeroTier on a New Raspberry Pi

If you need to set up ZeroTier on a new Raspberry Pi, follow these steps:

### Prerequisites
- Raspberry Pi with Raspberry Pi OS installed
- Internet connection
- Access to the Pi (via Raspberry Pi Connect, monitor/keyboard, or local SSH)

### Installation Steps

1. **Install ZeroTier on the Raspberry Pi:**
```bash
curl -s https://install.zerotier.com | sudo bash
```

2. **Join the network:**
```bash
sudo zerotier-cli join 2873fd00f2d70904
```

3. **Verify the Pi joined:**
```bash
sudo zerotier-cli listnetworks
```

You'll see status as "ACCESS_DENIED" initially.

4. **Authorize the Pi:**
- Go to https://my.zerotier.com
- Log in and navigate to network `2873fd00f2d70904`
- Click "Member Devices" tab
- Find the new Pi device (you can identify it by the MAC address or hostname)
- Check the "Auth" checkbox
- Note the "Managed IP" assigned to the Pi (e.g., `10.135.127.xxx`)

5. **Verify connection:**
```bash
sudo zerotier-cli listnetworks
```

Should now show:
```
200 listnetworks 2873fd00f2d70904 my-first-network ... OK PRIVATE ztxxxxxx 10.135.127.xxx/24
```

6. **Enable SSH (if not already enabled):**
```bash
sudo systemctl enable ssh
sudo systemctl start ssh
```

7. **Make ZeroTier start on boot:**
```bash
sudo systemctl enable zerotier-one
```

8. **Test connection from another device:**
```bash
# From your computer (already on ZeroTier network)
ping <new-pi-ip>
ssh <username>@<new-pi-ip>
```

9. **Update this documentation** with the new Pi's IP address!

---

## Advanced: VNC Access (Remote Desktop)

If you need graphical access to the Raspberry Pi:

1. **Enable VNC on the Pi:**
```bash
sudo raspi-config
# Navigate to: Interface Options → VNC → Enable
```

2. **Install VNC Viewer on your computer:**
https://www.realvnc.com/en/connect/download/viewer/

3. **Connect using the ZeroTier IP:**
- Open VNC Viewer
- Enter: `10.135.127.86`
- Enter Pi username and password
---

## Quick Reference

### Useful Commands

```bash
# Check ZeroTier status
sudo zerotier-cli info

# List joined networks
sudo zerotier-cli listnetworks

# Join a network
sudo zerotier-cli join <network-id>

# Leave a network
sudo zerotier-cli leave <network-id>

# Check peer connections
sudo zerotier-cli peers

# SSH to Raspberry Pi
ssh nfetestpi2@10.135.127.86
```

### Network Details
- **Network ID:** `2873fd00f2d70904`
- **Network Name:** `my-first-network`
- **Pi IP:** `10.135.127.86`
- **Pi Username:** `nfetestpi2`

---

*Last updated: 2026-03-28*

# DDSU666 (Direct chint meter ) + mbpoll Command Reference

**Version**: 1.0  
**Prepared For**: Field &amp; Deployment Teams  
**Platform**: Raspberry Pi / Linux  
**Tool**: mbpoll

1. #### Purpose

This document explains how to communicate with the CHINT DDSU666 Direct Smart Meter using Modbus RTU and the mbpoll tool.

It covers:  
• Reading electrical parameters  
• Setting meter addresses  
• Verifying communication  
• Preparing for OpenEMS integration

#### 2. Hardware &amp; Software Requirements

**Hardware**  
• DDSU666 (Direct Version)  
• RS485 → USB Converter  
• Raspberry Pi / Linux PC  
• Correct RS485 wiring (A(converter)↔24(meter com-port terminal), B(converter)↔25(meter com-port terminal), GND recommended)

**Software**  
Install mbpoll:

> sudo apt update  
> sudo apt install mbpoll

Check serial port:

> ls /dev/ttyUSB\*

Example output:

> /dev/ttyUSB0

#### 3. Communication Parameters (Confirmed)

<table border="0" cellpadding="0" cellspacing="0" class="MsoNormalTable" id="bkmrk-parameter-value-prot" style="border-collapse: collapse; width: 68.6905%; height: 160.172px;"><tbody><tr style="height: 17.7969px;"><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">**Parameter**

</td><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">**Value**

</td></tr><tr style="height: 17.7969px;"><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">Protocol

</td><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">Modbus RTU

</td></tr><tr style="height: 17.7969px;"><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">Baud Rate

</td><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">9600

</td></tr><tr style="height: 17.7969px;"><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">Data Bits

</td><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">8

</td></tr><tr style="height: 17.7969px;"><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">Parity

</td><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">None

</td></tr><tr style="height: 17.7969px;"><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">Stop Bits

</td><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">2

</td></tr><tr style="height: 17.7969px;"><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">Format

</td><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">8N2

</td></tr><tr style="height: 17.7969px;"><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">Float Order

</td><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">Big Endian

</td></tr><tr style="height: 17.7969px;"><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">Addressing

</td><td style="width: 0%; padding: 0in 5.4pt; height: 17.7969px;" valign="top" width="288">0-Based

</td></tr></tbody></table>

These parameters must always be used.

#### 4. Standard mbpoll Format

All commands follow this format:

> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:float -B -0 -r &lt;register&gt; -c &lt;count&gt; /dev/ttyUSB0 -a &lt;id&gt; -1

Where:  
• &lt;register&gt; = Modbus register  
• &lt;count&gt; = Number of values  
• &lt;id&gt; = Meter address (NO.)

#### 5. Electrical Parameters

**Summary:**

> Voltage: 0x2000  
> Current: 0x2002  
> Active Power: 0x2004  
> Power Factor: 0x200A  
> Frequency: 0x200E  
> Energy: 0x4000

##### 5.1 Voltage (V) — Register 0x2000

> **Meter ID = 1**  
> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:float -B -0 \\  
> -r 0x2000 -c 1 /dev/ttyUSB0 -a 1 -1  
> **Meter ID = 2**  
> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:float -B -0 \\  
> -r 0x2000 -c 1 /dev/ttyUSB0 -a 2 -1

#####   
5.2 Current (A) — Register 0x2002

> **Meter ID = 1**  
> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:float -B -0 \\  
> -r 0x2002 -c 1 /dev/ttyUSB0 -a 1 -1  
> **Meter ID = 2**  
> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:float -B -0 \\  
> -r 0x2002 -c 1 /dev/ttyUSB0 -a 2 -1

#####   
5.3 Active Power — Register 0x2004

> **Meter ID = 1**  
> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:float -B -0 \\  
> -r 0x2004 -c 1 /dev/ttyUSB0 -a 1 -1
> 
> **Meter ID = 2**  
> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:float -B -0 \\  
> -r 0x2004 -c 1 /dev/ttyUSB0 -a 2 -1

#####   
5.4 Power Factor — Register 0x200A

> **Meter ID = 1**  
> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:float -B -0 \\  
> -r 0x200A -c 1 /dev/ttyUSB0 -a 1 -1  
> **Meter ID = 2**  
> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:float -B -0 \\  
> -r 0x200A -c 1 /dev/ttyUSB0 -a 2 -1

#####   
5.5 Frequency (Hz) — Register 0x200E

> **Meter ID = 1**  
> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:float -B -0 \\  
> -r 0x200E -c 1 /dev/ttyUSB0 -a 1 -1  
> **Meter ID = 2**  
> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:float -B -0 \\  
> -r 0x200E -c 1 /dev/ttyUSB0 -a 2 -1

#####   
5.6 Energy (kWh) — Register 0x4000

> **Meter ID = 1**  
> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:float -B -0 \\  
> -r 0x4000 -c 1 /dev/ttyUSB0 -a 1 -1  
> **Meter ID = 2**  
> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:float -B -0 \\  
> -r 0x4000 -c 1 /dev/ttyUSB0 -a 2 -1

#### 6. Reading Multiple Values

  
Use **-c** option to read multiple registers.

**Example ( Voltage + Current Together)**

> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:float -B -0 \\  
> -r 0x2000 -c 2 /dev/ttyUSB0 -a 1 -1

#### 7. Meter Address

> **Register: 0x0006**
> 
> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:int16 -0 \\  
> -r 0x0006 -c 1 /dev/ttyUSB0 -a 2 -1
> 
> **Example Output:**  
> \[6\]: 2

#### 8. Changing Address

- Only one meter connected.
- Power cycle after change.

> **Change Address (2 → 1)**  
> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:int16 -0 \\  
> -r 0x0006 /dev/ttyUSB0 -a 2 -W -- 1  
> **Power Cycle**  
> Turn OFF → ON the meter.  
> **Verify**  
> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:int16 -0 \\  
> -r 0x0006 -c 1 /dev/ttyUSB0 -a 1 -1

#### 9. Health Check

  
Voltage should be 220–240V.

> mbpoll -m rtu -b 9600 -P none -s 2 -t 4:float -B -0 \\  
> -r 0x2000 -c 1 /dev/ttyUSB0 -a 1 -1

#### 10. Common Issues

  
**Timeout Errors**  
• Duplicate IDs  
• Wrong wiring  
• Wrong stop bits  
• Multiple meters during setup

  
**Incorrect Float Values**  
Use -B option.

  
**Current / Power = 0**

Normal when:  
• No load  
• Bench testing

#### 11. Deployment Workflow

For large installations:  
• Connect one meter  
• Convert to Modbus  
• Set address  
• Test voltage  
• Install  
• Repeat  
• Never deploy duplicate addresses.

> Connect → Configure → Test → Install

#### 12. System Status

  
✔ Modbus Enabled  
✔ 9600 8N2 Confirmed  
✔ Big-Endian Floats  
✔ Multi-meter Bus Working  
✔ Ready for OpenEMS

# Running OpenEMS Edge on a Raspberry PI

This guide explains how to:

1. Install and run **OpenEMS Edge on a Raspberry Pi**
2. Configure WebSocket + simulation
3. Run **OpenEMS UI on a macOS machine (not on the Pi)**
4. Connect the UI to the Edge over the internet

The structure is intentionally split into two clear parts:

- **PART A — Raspberry Pi (Edge)**
- **PART B — macOS Machine (OpenEMS UI)**

---

# ============================

# PART A — Raspberry Pi (Edge)

# ============================

## 1. Raspberry Pi OS Setup (Headless)

Use Raspberry Pi Imager:

- Device: Raspberry Pi 4
- OS: Raspberry Pi OS Lite (64‑bit)
- Configure:
    
    
    - Hostname
    - Username &amp; password
    - Enable SSH
    - Configure Wi‑Fi
    - Enable Raspberry Pi Connect

Boot the Pi and connect via:

- SSH
- OR Raspberry Pi Connect

---

## 2. Install Java 21 (Temurin ARM64)

On the Pi:

```bash
sudo apt update
sudo apt install -y wget apt-transport-https gpg

wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public \
 | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/adoptium.gpg > /dev/null

echo "deb https://packages.adoptium.net/artifactory/deb \
$(awk -F= '/^VERSION_CODENAME/{print $2}' /etc/os-release) main" \
 | sudo tee /etc/apt/sources.list.d/adoptium.list

sudo apt update
sudo apt install -y temurin-21-jdk

```

Verify:

```bash
java -version

```

---

## 3. Install OpenEMS Edge

```bash
mkdir -p ~/downloads
cd ~/downloads
wget https://github.com/OpenEMS/openems/releases/download/2025.11.0/openems-edge.jar
sudo chmod +x openems-edge.jar

sudo mkdir -p /usr/lib/openems
sudo mv openems-edge.jar /usr/lib/openems/
sudo mkdir -p /etc/openems.d

```

---

## 4. Configure systemd Service

Create:

```bash
sudo nano /etc/systemd/system/openems.service

```

Paste:

```ini
[Unit]
Description=OpenEMS Edge
After=network.target

[Service]
User=root
Group=root
Type=notify
WorkingDirectory=/usr/lib/openems
ExecStart=/usr/bin/java -Dfelix.cm.dir=/etc/openems.d/ \
  -jar /usr/lib/openems/openems-edge.jar
SuccessExitStatus=143
Restart=always
RestartSec=10
WatchdogSec=60

[Install]
WantedBy=multi-user.target

```

Enable &amp; start:

```bash
sudo systemctl daemon-reload
sudo systemctl enable openems
sudo systemctl start openems

```

Check:

```bash
systemctl status openems

```

---

## 5. Access OpenEMS Config Manager

On the Pi, open:

```
http://localhost:8080/system/console/configMgr

```

---

## 6. Add Required Components

In Config Manager:

1. Add a **Scheduler** (any default scheduler)
2. Add **Controller.Api.Websocket**
    
    
    - Port: 8085
    - Enabled: true

Restart Edge:

```bash
sudo systemctl restart openems

```

Verify WebSocket is listening:

```bash
sudo ss -lntp | grep 8085

```

You should see Java listening on port 8085.

---

## 7. (Optional) Add Simulation Components

In Config Manager, add:

- Simulator ESS
- Simulator Grid Meter
- Simulator PV

Save and restart OpenEMS.

---

# =====================================

# PART B — macOS Machine (OpenEMS UI)

# =====================================

## 1. Install Docker Desktop

```bash
brew install --cask docker
open -a Docker

```

Wait until Docker reports "Docker is running".

Verify:

```bash
docker version

```

You must see both Client and Server.

---

## 2. Clone OpenEMS Source

```bash
git clone -b 2025.11.0 https://github.com/OpenEMS/openems
cd openems

```

---

## 3. Build OpenEMS UI Image

```bash
docker build . \
  -t openems_ui \
  -f tools/docker/ui/Dockerfile.edge

```

---

## 4. Run OpenEMS UI

Replace YOUR\_PI\_IP with:

- Public IP
- OR VPN IP
- OR Public DNS

Example:

```bash
docker container run \
  -e WEBSOCKET_HOST=YOUR_PI_IP \
  -p 80:80 \
  -p 443:443 \
  --restart unless-stopped \
  --name openems_ui_container \
  openems_ui

```

---

## 5. Open the UI

On your Mac:

```
http://localhost/login

```

Default login:

- Username: admin
- Password: admin

If UI shows "disconnected":

- Confirm port 8085 is listening on the Pi
- Confirm WebSocket controller exists
- Confirm WEBSOCKET\_HOST is correct

---

# Why UI Runs on macOS and Edge Runs on Pi

- Edge interacts with hardware and benefits from native systemd management
- UI behaves like a stateless web application and is ideal for containerization
- Separating them improves stability and flexibility

---

# Troubleshooting

- UI loads but no connection → check port 8085
- Nothing listening on 8085 → WebSocket not configured
- Docker errors on Mac → ensure Docker Desktop is running

---

# Security Notes

- Prefer VPN/tunnel (Tailscale/WireGuard) over port forwarding
- Use SSH key-based authentication
- Do not expose ConfigMgr (8080) publicly

---

You now have:

- OpenEMS Edge running on Raspberry Pi
- WebSocket enabled
- Optional simulation components
- OpenEMS UI running on macOS
- UI connected over internet

<div drawio-diagram="79"><img src="https://bookstack.nearlyfreeenergy.com/uploads/images/drawio/2026-02/drawing-4-1770875762.png" alt=""/></div>

# DTSU666 3‑Phase + mbpoll Command Reference

---

# 🔌 Standard Communication Settings (DTSU666)

Most DTSU666 meters use:

<div class="relative w-full my-4" id="bkmrk-protocol-%3A-modbus-rt"><div class=""><div class="relative"><div class="h-full min-h-0 min-w-0"><div class="h-full min-h-0 min-w-0"><div class="border corner-superellipse/1.1 border-token-border-light bg-token-bg-elevated-secondary rounded-3xl"><div class="corner-superellipse/1.1 rounded-3xl bg-token-bg-elevated-secondary"><div class="relative z-0 flex max-w-full"><div class="q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch ͼk ͼy" dir="ltr" id="bkmrk-protocol-%3A-modbus-rt-1"><div class="cm-scroller"><div class="cm-content q9tKkq_readonly">Protocol : Modbus RTU  
Baud Rate : 9600  
Data Bits : 8  
Parity : None  
Stop Bits : 2  
Mode : Big‑endian  
Table : Input Registers (FC04)</div></div></div></div></div></div></div></div><div class=""><div class="">  
</div></div></div></div></div>Base communication block used in all commands:

<div class="relative w-full my-4" id="bkmrk--m-rtu--b-9600--p-no"><div class=""><div class="relative"><div class="h-full min-h-0 min-w-0"><div class="h-full min-h-0 min-w-0"><div class="border corner-superellipse/1.1 border-token-border-light bg-token-bg-elevated-secondary rounded-3xl"><div class="corner-superellipse/1.1 rounded-3xl bg-token-bg-elevated-secondary"><div class="relative z-0 flex max-w-full"><div class="q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch ͼk ͼy" dir="ltr" id="bkmrk--m-rtu--b-9600--p-no-1"><div class="cm-scroller"><div class="cm-content q9tKkq_readonly"><span class="ͼu">-m</span> rtu <span class="ͼu">-b</span> <span class="ͼq">9600</span> <span class="ͼu">-P</span> none <span class="ͼu">-s</span> <span class="ͼq">2</span></div></div></div></div></div></div></div></div><div class=""><div class="">  
</div></div></div></div></div>---

# 🧠 Critical Flags (Important)

<div class="TyagGW_tableContainer" id="bkmrk-flag-meaning-require"><div class="group TyagGW_tableWrapper flex flex-col-reverse w-fit" tabindex="-1"><table class="w-fit min-w-(--thread-content-width)" data-end="979" data-start="620"><thead data-end="650" data-start="620"><tr data-end="650" data-start="620"><th class="" data-col-size="sm" data-end="627" data-start="620">Flag</th><th class="" data-col-size="sm" data-end="637" data-start="627">Meaning</th><th class="" data-col-size="sm" data-end="650" data-start="637">Required?</th></tr></thead><tbody data-end="979" data-start="684"><tr data-end="734" data-start="684"><td data-col-size="sm" data-end="693" data-start="684">`-t 3`</td><td data-col-size="sm" data-end="725" data-start="693">Input Registers (Function 04)</td><td data-col-size="sm" data-end="734" data-start="725">✅ Yes</td></tr><tr data-end="779" data-start="735"><td data-col-size="sm" data-end="746" data-start="735">`:float`</td><td data-col-size="sm" data-end="770" data-start="746">32‑bit floating point</td><td data-col-size="sm" data-end="779" data-start="770">✅ Yes</td></tr><tr data-end="820" data-start="780"><td data-col-size="sm" data-end="787" data-start="780">`-B`</td><td data-col-size="sm" data-end="811" data-start="787">Big‑endian word order</td><td data-col-size="sm" data-end="820" data-start="811">✅ Yes</td></tr><tr data-end="861" data-start="821"><td data-col-size="sm" data-end="828" data-start="821">`-0`</td><td data-col-size="sm" data-end="852" data-start="828">Zero‑based addressing</td><td data-col-size="sm" data-end="861" data-start="852">✅ Yes</td></tr><tr data-end="899" data-start="862"><td data-col-size="sm" data-end="874" data-start="862">`-a <id>`</td><td data-col-size="sm" data-end="890" data-start="874">Slave address</td><td data-col-size="sm" data-end="899" data-start="890">✅ Yes</td></tr><tr data-end="931" data-start="900"><td data-col-size="sm" data-end="907" data-start="900">`-1`</td><td data-col-size="sm" data-end="919" data-start="907">Poll once</td><td data-col-size="sm" data-end="931" data-start="919">Optional</td></tr><tr data-end="979" data-start="932"><td data-col-size="sm" data-end="944" data-start="932">`-l 5000`</td><td data-col-size="sm" data-end="967" data-start="944">Poll every 5 seconds</td><td data-col-size="sm" data-end="979" data-start="967">Optional</td></tr></tbody></table>

</div></div>---

---

## 🔹 Phase‑to‑Neutral Voltages (L1‑N, L2‑N, L3‑N)

Register: `0x2006`

<div class="relative w-full my-4" id="bkmrk-mbpoll--m-rtu--b-960"><div class=""><div class="relative"><div class="h-full min-h-0 min-w-0"><div class="h-full min-h-0 min-w-0"><div class="border corner-superellipse/1.1 border-token-border-light bg-token-bg-elevated-secondary rounded-3xl"><div class="corner-superellipse/1.1 rounded-3xl bg-token-bg-elevated-secondary"><div class="relative z-0 flex max-w-full"><div class="q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch ͼk ͼy" dir="ltr" id="bkmrk-mbpoll--m-rtu--b-960-1"><div class="cm-scroller"><div class="cm-content q9tKkq_readonly">mbpoll <span class="ͼu">-m</span> rtu <span class="ͼu">-b</span> <span class="ͼq">9600</span> <span class="ͼu">-P</span> none <span class="ͼu">-s</span> <span class="ͼq">2</span> \  
<span class="ͼu">-t</span> <span class="ͼq">3</span>:float <span class="ͼu">-B</span> <span class="ͼu">-0</span> \  
<span class="ͼu">-r</span> 0x2006 <span class="ͼu">-c</span> <span class="ͼq">3</span> \  
/dev/ttyUSB0 <span class="ͼu">-a</span> <span class="ͼq">1</span> <span class="ͼu">-1</span></div></div></div></div></div></div></div></div><div class=""><div class="">  
</div></div></div></div></div>---

## 🔹 Line‑to‑Line Voltages (L1‑L2, L2‑L3, L3‑L1)

Register: `0x2000`

<div class="relative w-full my-4" id="bkmrk-mbpoll--m-rtu--b-960-2"><div class=""><div class="relative"><div class="h-full min-h-0 min-w-0"><div class="h-full min-h-0 min-w-0"><div class="border corner-superellipse/1.1 border-token-border-light bg-token-bg-elevated-secondary rounded-3xl"><div class="corner-superellipse/1.1 rounded-3xl bg-token-bg-elevated-secondary"><div class="relative z-0 flex max-w-full"><div class="q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch ͼk ͼy" dir="ltr" id="bkmrk-mbpoll--m-rtu--b-960-3"><div class="cm-scroller"><div class="cm-content q9tKkq_readonly">mbpoll <span class="ͼu">-m</span> rtu <span class="ͼu">-b</span> <span class="ͼq">9600</span> <span class="ͼu">-P</span> none <span class="ͼu">-s</span> <span class="ͼq">2</span> \  
<span class="ͼu">-t</span> <span class="ͼq">3</span>:float <span class="ͼu">-B</span> <span class="ͼu">-0</span> \  
<span class="ͼu">-r</span> 0x2000 <span class="ͼu">-c</span> <span class="ͼq">3</span> \  
/dev/ttyUSB0 <span class="ͼu">-a</span> <span class="ͼq">1</span> <span class="ͼu">-1</span></div></div></div></div></div></div></div></div><div class=""><div class="">  
</div></div></div></div></div>---

## 🔹 Phase Currents (L1, L2, L3)

Register: `0x200C`

<div class="relative w-full my-4" id="bkmrk-mbpoll--m-rtu--b-960-4"><div class=""><div class="relative"><div class="h-full min-h-0 min-w-0"><div class="h-full min-h-0 min-w-0"><div class="border corner-superellipse/1.1 border-token-border-light bg-token-bg-elevated-secondary rounded-3xl"><div class="corner-superellipse/1.1 rounded-3xl bg-token-bg-elevated-secondary"><div class="relative z-0 flex max-w-full"><div class="q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch ͼk ͼy" dir="ltr" id="bkmrk-mbpoll--m-rtu--b-960-5"><div class="cm-scroller"><div class="cm-content q9tKkq_readonly">mbpoll <span class="ͼu">-m</span> rtu <span class="ͼu">-b</span> <span class="ͼq">9600</span> <span class="ͼu">-P</span> none <span class="ͼu">-s</span> <span class="ͼq">2</span> \  
<span class="ͼu">-t</span> <span class="ͼq">3</span>:float <span class="ͼu">-B</span> <span class="ͼu">-0</span> \  
<span class="ͼu">-r</span> 0x200C <span class="ͼu">-c</span> <span class="ͼq">3</span> \  
/dev/ttyUSB0 <span class="ͼu">-a</span> <span class="ͼq">1</span> <span class="ͼu">-1</span></div></div></div></div></div></div></div></div><div class=""><div class="">  
</div></div></div></div></div>---

## 🔹 Total Active Power (kW)

Register: `0x2012`

<div class="relative w-full my-4" id="bkmrk-mbpoll--m-rtu--b-960-6"><div class=""><div class="relative"><div class="h-full min-h-0 min-w-0"><div class="h-full min-h-0 min-w-0"><div class="border corner-superellipse/1.1 border-token-border-light bg-token-bg-elevated-secondary rounded-3xl"><div class="corner-superellipse/1.1 rounded-3xl bg-token-bg-elevated-secondary"><div class="relative z-0 flex max-w-full"><div class="q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch ͼk ͼy" dir="ltr" id="bkmrk-mbpoll--m-rtu--b-960-7"><div class="cm-scroller"><div class="cm-content q9tKkq_readonly">mbpoll <span class="ͼu">-m</span> rtu <span class="ͼu">-b</span> <span class="ͼq">9600</span> <span class="ͼu">-P</span> none <span class="ͼu">-s</span> <span class="ͼq">2</span> \  
<span class="ͼu">-t</span> <span class="ͼq">3</span>:float <span class="ͼu">-B</span> <span class="ͼu">-0</span> \  
<span class="ͼu">-r</span> 0x2012 <span class="ͼu">-c</span> <span class="ͼq">1</span> \  
/dev/ttyUSB0 <span class="ͼu">-a</span> <span class="ͼq">1</span> <span class="ͼu">-1</span></div></div></div></div></div></div></div></div><div class=""><div class="">  
</div></div></div></div></div>---

## 🔹 Frequency (Hz)

Register: `0x2044`

<div class="relative w-full my-4" id="bkmrk-mbpoll--m-rtu--b-960-8"><div class=""><div class="relative"><div class="h-full min-h-0 min-w-0"><div class="h-full min-h-0 min-w-0"><div class="border corner-superellipse/1.1 border-token-border-light bg-token-bg-elevated-secondary rounded-3xl"><div class="corner-superellipse/1.1 rounded-3xl bg-token-bg-elevated-secondary"><div class="relative z-0 flex max-w-full"><div class="q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch ͼk ͼy" dir="ltr" id="bkmrk-mbpoll--m-rtu--b-960-9"><div class="cm-scroller"><div class="cm-content q9tKkq_readonly">mbpoll <span class="ͼu">-m</span> rtu <span class="ͼu">-b</span> <span class="ͼq">9600</span> <span class="ͼu">-P</span> none <span class="ͼu">-s</span> <span class="ͼq">2</span> \  
<span class="ͼu">-t</span> <span class="ͼq">3</span>:float <span class="ͼu">-B</span> <span class="ͼu">-0</span> \  
<span class="ͼu">-r</span> 0x2044 <span class="ͼu">-c</span> <span class="ͼq">1</span> \  
/dev/ttyUSB0 <span class="ͼu">-a</span> <span class="ͼq">1</span> <span class="ͼu">-1</span></div></div></div></div></div></div></div></div><div class=""><div class="">  
</div></div></div></div></div>---

## 🔹 Total Active Energy (kWh)

Register: `0x4000`

<div class="relative w-full my-4" id="bkmrk-mbpoll--m-rtu--b-960-10"><div class=""><div class="relative"><div class="h-full min-h-0 min-w-0"><div class="h-full min-h-0 min-w-0"><div class="border corner-superellipse/1.1 border-token-border-light bg-token-bg-elevated-secondary rounded-3xl"><div class="corner-superellipse/1.1 rounded-3xl bg-token-bg-elevated-secondary"><div class="relative z-0 flex max-w-full"><div class="q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch ͼk ͼy" dir="ltr" id="bkmrk-mbpoll--m-rtu--b-960-11"><div class="cm-scroller"><div class="cm-content q9tKkq_readonly">mbpoll <span class="ͼu">-m</span> rtu <span class="ͼu">-b</span> <span class="ͼq">9600</span> <span class="ͼu">-P</span> none <span class="ͼu">-s</span> <span class="ͼq">2</span> \  
<span class="ͼu">-t</span> <span class="ͼq">3</span>:float <span class="ͼu">-B</span> <span class="ͼu">-0</span> \  
<span class="ͼu">-r</span> 0x4000 <span class="ͼu">-c</span> <span class="ͼq">1</span> \  
/dev/ttyUSB0 <span class="ͼu">-a</span> <span class="ͼq">1</span> <span class="ͼu">-1</span></div></div></div></div></div></div></div></div><div class=""><div class="">  
</div></div></div></div></div>---

# 🔁 Continuous Polling Example (Every 5 Seconds)

<div class="relative w-full my-4" id="bkmrk-mbpoll--m-rtu--b-960-12"><div class=""><div class="relative"><div class="h-full min-h-0 min-w-0"><div class="h-full min-h-0 min-w-0"><div class="border corner-superellipse/1.1 border-token-border-light bg-token-bg-elevated-secondary rounded-3xl"><div class="corner-superellipse/1.1 rounded-3xl bg-token-bg-elevated-secondary"><div class="relative z-0 flex max-w-full"><div class="q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch ͼk ͼy" dir="ltr" id="bkmrk-mbpoll--m-rtu--b-960-13"><div class="cm-scroller"><div class="cm-content q9tKkq_readonly">mbpoll <span class="ͼu">-m</span> rtu <span class="ͼu">-b</span> <span class="ͼq">9600</span> <span class="ͼu">-P</span> none <span class="ͼu">-s</span> <span class="ͼq">2</span> \  
<span class="ͼu">-t</span> <span class="ͼq">3</span>:float <span class="ͼu">-B</span> <span class="ͼu">-0</span> \  
<span class="ͼu">-r</span> 0x2006 <span class="ͼu">-c</span> <span class="ͼq">1</span> \  
<span class="ͼu">-l</span> <span class="ͼq">5000</span> \  
/dev/ttyUSB0 <span class="ͼu">-a</span> <span class="ͼq">1</span></div></div></div></div></div></div></div></div><div class=""><div class="">  
</div></div></div></div></div>---

# 🔢 Change Slave Address (Only One Meter Connected)

⚠ Use Holding Registers (Function 03) for configuration.

Register: `0x002E`

<div class="relative w-full my-4" id="bkmrk-mbpoll--m-rtu--b-960-14"><div class=""><div class="relative"><div class="h-full min-h-0 min-w-0"><div class="h-full min-h-0 min-w-0"><div class="border corner-superellipse/1.1 border-token-border-light bg-token-bg-elevated-secondary rounded-3xl"><div class="corner-superellipse/1.1 rounded-3xl bg-token-bg-elevated-secondary"><div class="relative z-0 flex max-w-full"><div class="q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch ͼk ͼy" dir="ltr" id="bkmrk-mbpoll--m-rtu--b-960-15"><div class="cm-scroller"><div class="cm-content q9tKkq_readonly">mbpoll <span class="ͼu">-m</span> rtu <span class="ͼu">-b</span> <span class="ͼq">9600</span> <span class="ͼu">-P</span> none <span class="ͼu">-s</span> <span class="ͼq">2</span> \  
<span class="ͼu">-t</span> <span class="ͼq">4</span>:int16 <span class="ͼu">-0</span> \  
<span class="ͼu">-r</span> 0x002E \  
/dev/ttyUSB0 <span class="ͼu">-a</span> <span class="ͼq">1</span> <span class="ͼu">-W</span> <span class="ͼu">--</span> <span class="ͼq">5</span></div></div></div></div></div></div></div></div><div class=""><div class="">  
</div></div></div></div></div>Changes slave ID from 1 → 5.

---

# 🧪 Quick Communication Test

Fastest health check:

<div class="relative w-full my-4" id="bkmrk-mbpoll--m-rtu--b-960-16"><div class=""><div class="relative"><div class="h-full min-h-0 min-w-0"><div class="h-full min-h-0 min-w-0"><div class="border corner-superellipse/1.1 border-token-border-light bg-token-bg-elevated-secondary rounded-3xl"><div class="corner-superellipse/1.1 rounded-3xl bg-token-bg-elevated-secondary"><div class="relative z-0 flex max-w-full"><div class="q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch ͼk ͼy" dir="ltr" id="bkmrk-mbpoll--m-rtu--b-960-17"><div class="cm-scroller"><div class="cm-content q9tKkq_readonly">mbpoll <span class="ͼu">-m</span> rtu <span class="ͼu">-b</span> <span class="ͼq">9600</span> <span class="ͼu">-P</span> none <span class="ͼu">-s</span> <span class="ͼq">2</span> \  
<span class="ͼu">-t</span> <span class="ͼq">3</span>:float <span class="ͼu">-B</span> <span class="ͼu">-0</span> \  
<span class="ͼu">-r</span> 0x2006 <span class="ͼu">-c</span> <span class="ͼq">1</span> \  
/dev/ttyUSB0 <span class="ͼu">-a</span> <span class="ͼq">1</span> <span class="ͼu">-1</span></div></div></div></div></div></div></div></div><div class=""><div class="">  
</div></div></div></div></div>If you see ~230V → communication confirmed.

---

# 🚨 Troubleshooting Quick Guide

<div class="TyagGW_tableContainer" id="bkmrk-symptom-likely-cause"><div class="group TyagGW_tableWrapper flex flex-col-reverse w-fit" tabindex="-1"><table class="w-fit min-w-(--thread-content-width)" data-end="2994" data-start="2743"><thead data-end="2769" data-start="2743"><tr data-end="2769" data-start="2743"><th class="" data-col-size="sm" data-end="2753" data-start="2743">Symptom</th><th class="" data-col-size="sm" data-end="2769" data-start="2753">Likely Cause</th></tr></thead><tbody data-end="2994" data-start="2798"><tr data-end="2835" data-start="2798"><td data-col-size="sm" data-end="2808" data-start="2798">Timeout</td><td data-col-size="sm" data-end="2835" data-start="2808">Wrong address or wiring</td></tr><tr data-end="2876" data-start="2836"><td data-col-size="sm" data-end="2850" data-start="2836">4200+ volts</td><td data-col-size="sm" data-end="2876" data-start="2850">Reading wrong register</td></tr><tr data-end="2911" data-start="2877"><td data-col-size="sm" data-end="2892" data-start="2877">-8192 values</td><td data-col-size="sm" data-end="2911" data-start="2892">Wrong data type</td></tr><tr data-end="2947" data-start="2912"><td data-col-size="sm" data-end="2931" data-start="2912">Nonsense numbers</td><td data-col-size="sm" data-end="2947" data-start="2931">Missing `-B`</td></tr><tr data-end="2994" data-start="2948"><td data-col-size="sm" data-end="2968" data-start="2948">No `/dev/ttyUSB0`</td><td data-col-size="sm" data-end="2994" data-start="2968">USB‑RS485 not detected</td></tr></tbody></table>

</div></div>

# SRNE ASP48120SH3 (Direct Hybrid Inverter) + mbpoll Command Reference

**Version**: 1.1
**Prepared For**: Field & Deployment Teams
**Platform**: Raspberry Pi / Linux
**Tool**: mbpoll / pymodbus

## 1. Purpose

Complete reference for the SRNE ASP48120SH3 three-phase hybrid inverter over Modbus RTU: what can be READ, what can be WRITTEN, and the tested limits. Validated against the live unit at Nansana on 2026-07-21 (slave address 1).

## 2. Hardware & Software Requirements

* SRNE ASP48120SH3, RS485 to USB converter (CH340), Raspberry Pi / Linux PC.
* Wiring: A(converter) to WiFi-port RJ45 pin 7 (RS485-A), B to pin 8 (RS485-B), GND to pin 2. The WiFi port carries the monitoring bus; the RS485/CAN port is for the battery BMS.
* Install: `sudo apt install mbpoll`  and/or  `pip install pymodbus`.

## 3. Serial parameters and function codes

* 9600 baud, 8 data bits, No parity, 1 stop bit (8N1). Slave address 1.
* READ: function code 03 (holding registers). 16-bit registers with scale factors (not 32-bit floats).
* WRITE: BOTH FC06 (write single) and FC16 (write multiple) are supported and tested. Note: the CHINT meters reject FC06, the inverter does NOT.
* mbpoll read flags: `-b 9600 -P none -s 1 -t 4 -0`.

## 4. Reading values (exhaustive, all ranges respond)

Every documented range answers FC03. Ranges (SRNE V1.7 segment map, confirmed on this unit):

**Product info (P00), 0x0000 to 0x0049**

* 0x000B machine type = 4 (integrated inverter-controller)
* 0x0014 software version = 925
* 0x001A RS485 address = 1 (read only)

**Controller / battery (P01), 0x0100 to 0x0122**

* 0x0100 SOC (%), 0x0101 battery V (x0.1), 0x0102 battery I (x0.1 signed, + charge / - discharge), 0x0103 device temp (reads 0, unused)
* 0x0104 to 0x0106 DC load V/I/P (0, no DC load on this unit), 0x0107 to 0x0111 PV panels 1/2 (0, no PV), 0x010B charge state (1 = quick charge)

**Inverter (P02), 0x0200 to 0x0237** (the main live telemetry, see the register-map page)

* state 0x0210, bus 0x0212, grid+inverter phase A 0x0213 to 0x0218, load 0x0219 to 0x021F, heat-sinks 0x0220 to 0x0223, PBus/NBus 0x0228/0x0229, 3-phase B/C V/I 0x022A to 0x022F, 3-phase B/C load 0x0230 to 0x0237.

**Settings / parameters, 0xE001 to 0xE02D** (writable, see section 5). Raw values present; battery voltage thresholds around 0xE006 to 0xE00E appear as 48V-system values (register/10 x 4), e.g. 144 = 57.6 V. Exact per-register meaning is TBD from the ASP settings doc.

**Settings F, 0xF000 to 0xF01F**: additional parameters (raw values present).

**Control commands, 0xDF00 to 0xDF09**: write-only, read back as 0.

Example reads (mbpoll):

    # battery block 0x0100 (dec 256), 4 regs
    mbpoll -m rtu -b 9600 -P none -s 1 -t 4 -0 -r 256 -c 4 -a 1 -1 <port>
    # inverter block 0x0210 (dec 528), 32 regs
    mbpoll -m rtu -b 9600 -P none -s 1 -t 4 -0 -r 528 -c 32 -a 1 -1 <port>
    # settings 0xE001 (dec 57345), 45 regs
    mbpoll -m rtu -b 9600 -P none -s 1 -t 4 -0 -r 57345 -c 45 -a 1 -1 <port>

## 5. Writing values (tested 2026-07-21)

The inverter accepts BOTH FC06 and FC16 and enforces a permission model:

* Read-only registers (telemetry, product info, e.g. 0x001A) REJECT writes with exception code 7 ("parameter is read only"). Tested.
* Settings registers (0xE0xx) ACCEPT writes (both FC06 and FC16), with no password or run-state lock on the tested registers (0xE015, 0xE01F, 0xE024). Tested via no-op write-back (wrote the current value, confirmed unchanged).
* Control commands (0xDF00 to 0xDF09) are write-only actions. NOT fired on the live unit because it feeds customers. Documented below.

**Exception code table (SRNE V1.7):** 1 illegal function, 2 illegal data address, 3 illegal data value, 4 operation failed, 5 password error, 7 read only, 8 cannot change while running, 9 password protection, 10 length error, 11 permission denied.

**Control command registers (DANGEROUS on a live system, documented only):**

* 0xDF00 power ON/OFF: 1 = on, 0 = off. OFF cuts inverter output, do NOT fire while it feeds customers.
* 0xDF01 reset: 1 = reset.
* 0xDF02 restore defaults: 0xAA wipes all settings.
* 0xDF03 clear current alarm: 1.
* 0xDF04 clear statistics: 1.
* 0xDF05 clear history: 1.
* 0xDF08 sleep/run: 0x5A5A sleep, 0xA5A5 run.

**How to write:**

    # mbpoll FC06 (write single): value as the last argument
    mbpoll -m rtu -b 9600 -P none -s 1 -t 4 -0 -r <dec_addr> -a 1 <port> <value>

    # pymodbus
    client.write_register(address=REG, value=V, device_id=1)     # FC06
    client.write_registers(address=REG, values=[V], device_id=1) # FC16

## 6. Tested limits summary

* CAN: read every range over FC03; write settings 0xE0xx with FC06 or FC16; read-only registers are protected (code 7).
* CAUTION: control commands 0xDF00 to 0xDF09 are live actions (power, reset, restore). Documented, NOT fired on the customer-feeding unit. Only fire with an outage window and explicit sign-off.
* UNKNOWN / next: exact meaning of each 0xE0xx and 0xF0xx setting (needs the ASP settings doc or careful change-and-revert testing offline); machine-state codes other than 2 (verify by observing transitions).

## 7. Preparing for OpenEMS integration

The validated telemetry map is a declarative table in `src/inverter/registers.py` (nfe-modbus-energy-logger), grouped by OpenEMS nature (ElectricityMeter grid/backup, SymmetricEss battery, OffGridBatteryInverter state). It maps 1:1 to a GoodWe-style defineModbusProtocol (FC3ReadRegistersTask + word elements + SCALE_FACTOR). Control writes map to FC16WriteRegistersTask on the 0xDF00 area and 0xE0xx settings.

# SRNE ASP48120SH3 Modbus Register Map (validated)

Validated Modbus register map for the SRNE ASP48120SH3 three-phase hybrid inverter, verified register-by-register against the live Nansana unit, including a **grid-off / grid-on transition test on 2026-07-27** that resolved the previously-unknown registers and corrected the battery-current sign.

**Bus**: RS485, 9600 8N1, function code 03 (read holding registers), slave address 1.
**Source of truth (code)**: `src/inverter/registers.py` in nfe-modbus-energy-logger.

## Valid register ranges (probed live)

* P00 product info: 0x0000 to 0x0049
* P01 battery / DC: 0x0100 to 0x0111
* P02 inverter telemetry: 0x0200 to **0x023F** (0x0240 and beyond return "Illegal data address")
* P03 control commands: 0xDF00 to 0xDF09 (write-only, read back 0)
* Settings E (writable params): 0xE001 to 0xE02D ; Settings F: 0xF000 to 0xF01F

## Live telemetry, full per-phase - VERIFIED

| quantity | phase A | phase B | phase C | notes |
| --- | --- | --- | --- | --- |
| grid voltage | 0x0213 | 0x022A | 0x022B | x0.1 V (all go to 0 when grid is off) |
| grid current | 0x0214 | **0x0238** | **0x0239** | x0.1 A. B/C live in the extended block, CONFIRMED grid-side by the transition test |
| grid frequency | 0x0215 | - | - | x0.01 Hz |
| grid active power | 0x023A | 0x023B | 0x023C | W (extended block, grid-side) |
| inverter voltage | 0x0216 | 0x022C | 0x022D | x0.1 V |
| inverter current | 0x0217 | 0x022E | 0x022F | x0.1 A (rises when off-grid, inverter sources the load) |
| inverter frequency | 0x0218 | - | - | x0.01 Hz |
| load current | 0x0219 | 0x0230 | 0x0231 | x0.1 A (load-side, holds through the transition) |
| load active power | 0x021B | 0x0232 | 0x0233 | W. No total register: sum the three phases |
| load reactive power | (derive) | 0x0234 | 0x0235 | var. Phase A: S=sqrt(P^2+Q^2) not given, derive |
| load apparent power | 0x021C | (derive) | (derive) | VA. B/C: derive S = sqrt(P^2 + Q^2) |
| load ratio | 0x021F | 0x0236 | 0x0237 | % |

Other P02: state 0x0210, password status 0x0211, bus V 0x0212 (x0.1) = PBus 0x0228 + NBus 0x0229, inverter DC component 0x021D (mV), mains charge current 0x021E (x0.1 A), heat-sink temps 0x0220/0x0221/0x0222 (x0.1 C, 0x0223 bogus), PV charge current 0x0224 (0, no PV), inverter fault 0x0226, charge status 0x0227. Extended grid block tail 0x023D/0x023E/0x023F (0/221/245/309 on grid) is grid-side reactive/apparent, exact split still to confirm.

## Battery / DC (P01) - VERIFIED

SOC 0x0100 (%), battery V 0x0101 (x0.1 V), battery current 0x0102 (x0.1 A, signed), device temp 0x0103 (reads 0, dead), DC load 0x0104-0x0106 (0), PV1 0x0107-0x0109 (0, no PV), charge state 0x010B, charge power 0x010E, PV2 0x010F-0x0111 (0).

**IMPORTANT - battery current sign is POSITIVE = DISCHARGE on this unit** (the OPPOSITE of the generic SRNE V1.7 doc). Proven by the 2026-07-27 off-grid test: with grid and PV both at 0, the battery is the only source, and while it was unambiguously discharging ~750 W to the loads it read **+14.2 A**; when the grid returned, discharge collapsed to +0.4 A (idle). So positive current = discharge, negative = charge.

## Grid-off / grid-on transition test (2026-07-27) - what died vs held

* GRID-side (went to 0 when utility cut, back live when restored): grid V A/B/C (0x0213/0x022A/0x022B), grid I A (0x0214), grid freq (0x0215), and the whole extended block 0x0238 to 0x023F (grid I B/C + grid power). This is how the extended block was identified.
* LOAD-side (held through the transition, source-independent): load I/P/Q per phase (0x0219, 0x021B, 0x0230-0x0237).
* INVERTER-side (rose off-grid as it took the load): inverter I A/B/C (0x0217/0x022E/0x022F).
* STATE 0x0210: **2 = on-grid / mains-bypass, 3 = off-grid / inverter-powered** (both codes validated by the transition). Charge state 0x010B: 0 off-grid, 1 on-grid.

## Corrections vs the generic SRNE V1.7 doc (do NOT trust the generic enums/signs)

* Battery current sign: **positive = discharge** (doc says positive = charge - WRONG here).
* Machine state 0x0210: 2 = running/mains-bypass, 3 = off-grid. NOT the generic "initialization/soft-start".
* Power factor 0x021A reads 0. Derive PF = active (0x021B) / apparent (0x021C).
* Device temperature 0x0103 reads 0. Use heat-sink temps 0x0220 to 0x0222.

## For the OpenEMS driver (important)

* There is NO inverter-output-power and NO ESS/battery AC-power register. The ESS SymmetricEss.ACTIVE_POWER must be DERIVED from battery DC power (0x0101 x 0x0102). Do NOT map load power 0x021B (that is the loads, phase A only).
* **Dc/ESS power sign**: since positive battery current = discharge, DcDischargePower = +V x I (do NOT negate). A negated formula reports a real discharge as a charge.
* Grid meter can now have per-phase current and power: grid I A/B/C (0x0214/0x0238/0x0239) and grid active power A/B/C (0x023A/0x023B/0x023C).
* Consumption/backup meter power from the load registers (0x021B/0x0232/0x0233 active, 0x0234/0x0235 reactive).

## Writes

Both FC06 and FC16 supported. Read-only registers reject with exception code 7. Settings 0xE0xx writable. Control 0xDF00 area (power/reset/restore) is dangerous on the live unit: documented, not fired.

# SRNE ASP48120SH3 Safe Settings Write: design, registers, and commissioning (#53)

## Purpose and scope

This page documents the SRNE ASP48120SH3 safe settings write feature (story #53): the ability to remotely change a bounded set of inverter parameters over Modbus, with every write guarded, verified by read back, and never retried. It records the design, the exact registers, the commissioning procedure, and, importantly, the current verification status so the work stays traceable and defendable.

Read this alongside the validated register map (page 126) and the mbpoll command reference (page 125).

## What can and cannot be written

The feature can change eight settings only. Each is disabled by default (sentinel -1), bounded, applied only when the configured target differs from the live reading, and verified by a fresh read back.

| # | Setting | Register (FC16) | Bounds | Units / raw multiplier |
|---|---|---|---|---|
| 0 | Discharge cutoff SoC | 0xE00F | 0 to 100 | percent, x1 |
| 1 | Stop charge current | 0xE01C | 0 to 100 A | amps, x10 (deci-amp raw) |
| 2 | Stop charge SoC | 0xE01D | 0 to 100 | percent, x1 |
| 3 | Low SoC alarm | 0xE01E | 0 to 100 | percent, x1 |
| 4 | Switch to line (grid) SoC | 0xE01F | 0 to 100 | percent, x1 |
| 5 | Switch to battery SoC | 0xE020 | 0 to 100 | percent, x1 |
| 6 | AC charge current limit | 0xE205 | 0 to 100 A | amps, x10 |
| 7 | Max total charge current limit | 0xE20A | 0 to 100 A | amps, x10 |

The current ceiling is MAX_BATTERY_CURRENT_A = 100 A, the continuous rating. The datasheet peak is 120 A for 3 seconds, so the continuous value is the correct, conservative cap.

It explicitly cannot: change charge or discharge time windows, command a specific charge or discharge power, change operating or source priority modes, start or stop the inverter, or reset or clear data.

## Safety design

Every write passes through the same defended path (component SrneBatteryInverterImpl, helper SafeWriteHandler in the io.openems.edge.ess.srne bundle):

1. Default off. Nothing writes unless the operator sets controlEnabled true in the gateway config. Default is false.
2. Machine state gate. A write is only queued when the inverter reports a verified stable state. Register 0x0210 value 2 (on-grid, mains bypass) is the only verified state; every other state, including off-grid (3), transitioning, fault, and undefined, blocks all writes.
3. Bounds. Each setting is range checked against the table above. An out of range target is rejected before any Modbus write and marked failed (terminal).
4. One shot per activation. The write state machine is IDLE, then QUEUED, then AWAITING_READBACK, then VERIFIED or FAILED. A setting is queued at most once per component activation; VERIFIED and FAILED are terminal, so there is no re-write and no storm even though reconciliation now runs every cycle.
5. Read back verification. After the FC16 write executes, a fresh read of the same register must equal the target to reach VERIFIED. A mismatch goes to FAILED.
6. Bounded wait, no retry. The read back is allowed up to 30 Edge cycles; on timeout the state is FAILED. A failed or mismatched write is never retried automatically.
7. Thread safe. The handler methods are synchronized so the cycle thread (reconcile) and the Modbus worker thread (execute and read back) transition state atomically.

The aggregate SAFE_WRITE_STATE channel surfaces the highest severity handler state so an operator can watch commissioning progress.

## The standalone topology fix (openems PR #23)

During #53 commissioning, gateway config v18 enabled control and targeted Low SoC alarm 15 to 16, but no FC16 write occurred and the read back stayed at 15. Root cause: gw-aaron runs a standalone Srne.Ess topology, so the generic ManagedSymmetricBatteryInverter run() path was never invoked, and reconciliation was hung off run(). The gateway was restored to the healthy v17 read only profile; the inverter setting did not change.

The fix moves the reconcile trigger to the Edge TOPIC_CYCLE_AFTER_PROCESS_IMAGE event, which fires every cycle in all topologies. It drives both the read back timeout advance and the queue, so the failure path works too. All guards above are unchanged; only the trigger moved.

## Commissioning procedure (staged)

The commissioning is deliberately low risk and staged, with a pre staged rollback:

1. v17: read only baseline, control disabled.
2. v18: enable control, target exactly one setting (Low SoC alarm 15 to 16), leave the other seven at -1 (disabled). Verify a fresh read back of 16 and SAFE_WRITE_STATE VERIFIED, with stable telemetry and no other writes.
3. v19: restore Low SoC alarm 16 to 15, keep control enabled, all other targets at -1.
4. Rollback profile (microgrid PR #33): a break glass config that targets only Low SoC alarm 15, used if v18 changes the inverter but verification fails.

Gate: the v19 enable step (microgrid PR #34) must not be deployed until v18 has been deployed and verified with SAFE_WRITE_STATE VERIFIED on the real inverter.

## Verification status (as of 2026-08-08)

Be precise here, because the live unit has not yet confirmed a write.

- Code reviewed at source level, including an adversarial second pass and mutation testing of the safety gates.
- Unit and integration tested in Java on JDK 21. Coverage includes: the write queues via the new event path in the standalone topology; control disabled never queues; a non verified machine state never queues (both mutation proven, that is, removing the guard makes the test fail with a real queued write); the one shot property, no re-queue across extra cycles; and, at unit level, the read back mismatch and timeout paths with no retry.
- Not yet verified on the live inverter. No setting has been successfully written and read back on the physical unit. The only live result so far is the v18 non write above, which exposed the topology bug. Live verification is pending: merge openems #23, build a new openems-edge image, then repeat the v18 15 to 16 commissioning gate on the real inverter.
- There is no Python live test harness for this. Writes are exercised through OpenEMS plus the gateway commissioning config and verified by Modbus read back, not by a standalone script.

## Traceability

- Story: nfe-modbus-energy-logger issue #53.
- Code: openems PR #21 (guarded write infrastructure, merged), openems PR #23 (standalone topology fix plus gate tests, in review).
- Deployment: microgrid-gateway PR #32 (v18 commission, merged), #33 (rollback pre stage), #34 (v19 enable). Gated as above.
- Registers: SRNE ASP48120SH3 Modbus Register Map, validated (page 126). mbpoll command reference (page 125).

## Live read test results (2026-08-08)

First live read of the eight settings on the pilot inverter (gw-aaron), via direct Modbus (mbpoll, FC03) with the OpenEMS edge and the nfe-monitor process stopped to free the RS485 bus. Read only, no writes. Accessed over Raspberry Pi Connect plus ZeroTier (nfetestpiaaron, 10.135.127.37).

| Setting | Register | Raw | Decoded |
|---|---|---|---|
| Discharge cutoff SoC | 0xE00F | 5 | 5 percent |
| Stop charge current | 0xE01C | 30 | 3.0 A |
| Stop charge SoC | 0xE01D | 100 | 100 percent |
| Low SoC alarm | 0xE01E | 15 | 15 percent |
| Switch to line (grid) SoC | 0xE01F | 10 | 10 percent |
| Switch to battery SoC | 0xE020 | 90 | 90 percent |
| AC charge current limit | 0xE205 | 1200 | 120.0 A |
| Max total charge current limit | 0xE20A | 1000 | 100.0 A |

Context registers: machine state 0x0210 = 3 (off-grid, inverter-powered), SoC 0x0100 = 92 percent.

Findings:

1. Low SoC alarm reads 15, matching the gateway config. This confirms the v18 15 to 16 commissioning write did not change the inverter (the standalone topology bug fixed in openems #23); the live value is still 15. This is the live evidence behind that finding.
2. Machine state is 3 (off-grid). The write feature only permits writes in the verified state (2, on-grid mains bypass), so a write attempted right now would be correctly blocked by the machine-state gate. A live write test must wait for the inverter to be on-grid.
3. Current scaling is x0.1 (deci-amp): AC charge limit 120.0 A, max charge 100.0 A, stop-charge current 3.0 A. SoC and percent settings are x1.
4. Bus collision confirmed live: both the OpenEMS edge and the nfe-monitor (F3) process were found mastering /dev/ttyUSB0 at the same time. The bus only freed after stopping both. F3 must not run a second Modbus master on this Pi.
5. The block read of 0xE001 to 0xE02D (count 45) returns Modbus exception 0x0A (gateway path unavailable) on this unit even with the bus free; read the settings individually or in small blocks.

Raw mbpoll output:

    [57359]  5      (0xE00F discharge cutoff SoC)
    [57372]  30     (0xE01C stop charge current)
    [57373]  100    (0xE01D stop charge SoC)
    [57374]  15     (0xE01E low SoC alarm)
    [57375]  10     (0xE01F switch to line SoC)
    [57376]  90     (0xE020 switch to battery SoC)
    [57861]  1200   (0xE205 AC charge current limit)
    [57866]  1000   (0xE20A max charge current limit)
    [528]    3      (0x0210 machine state)
    [256]    92     (0x0100 SoC)

Status: reads are now live-verified as above. The live WRITE test (Low SoC alarm 15 to 16, verify by fresh readback, restore to 15) is still pending, and requires both openems #23 deployed and the inverter in the verified on-grid state (it was off-grid at read time).
## Commissioning results — live on gw-aaron (2026-08-10)

The guarded settings-write path was commissioned end to end on the live Aaron pilot inverter (SRNE ASP48120SH3), using the low-risk representative setting LowSocAlarm 15 -> 16 -> 15.

Sequence:
- OpenEMS PR #23 merged (writes run from the Edge cycle so the standalone Srne.Ess topology schedules the FC16). Merge 485c075b.
- Corrected edge image nfe-v0.2.2 built and pinned by digest sha256:3828fc838a67045bc2b88f4347e1424ca6a284dde0602dce52d9d4256dfc1d1f.
- Gateway PR #36 (v20 settings-commissioning) deployed. Reconciler wrote 15 -> 16.

Evidence (edge logs):
```
Queued one-shot settings write [LOW_SOC_ALARM] from [15] to [16]
Settings write [LOW_SOC_ALARM] state [VERIFIED] after readback [16]
```
- Confirmed by a bus-exclusive mbpoll read: register 0xE01E = 16.
- Restored 16 -> 15; verified by three consecutive stable direct reads = 15.
- Final resting config: gateway PR #37 (v21) = read-only (controlEnabled=false, all targets -1) on nfe-v0.2.2; supersedes v20 so a redeploy cannot re-arm. Edge healthy, backend connected, machine state 2 Running (mains/bypass).

Two operational lessons banked:
- The write gate only fires in a live-validated verified machine state (state 2 here). While the flaky grid is down the inverter sits in state 3 (off-grid, unverified) and the guard correctly defers the write; that is not a failure, just wait for the grid.
- To read the RS485 bus directly with mbpoll you must stop both openems-edge and the mbpoll container and wait ~5 s for the bus to settle; reading sooner returns garbage (a spurious 1200 was observed).

Process note: settings changes must go through git -> deploy-gateway.sh, never hand-edited on the box. A read-only resting config (v21) is the safe default between commissioning windows.

# SRNE charge/discharge scheduling registers (self-decoded, #67)

## Summary

We self-decoded the SRNE ASP48120SH3 settings registers (V1.7 protocol PDF + a live read-scan of the pilot inverter, firmware v925, 2026-08-09). The key result: **time-of-use charge/discharge scheduling is implemented and writable**, even though real-time active-power dispatch is not. This is the arbitrage lever, and it is not firmware-blocked.

Aaron's SRNE email (2026-08-03) reported that `0xE047-0xE04D` (timed charge/discharge MAX POWER) and `0xE400/E401/E402` (grid active/PF/reactive power) return Modbus "Illegal data address" on our firmware. That is confirmed. But those are a different feature (instantaneous power dispatch). The actual **time-window schedule registers `0xE026-0xE032` are RW and implemented.**

## Charge / discharge schedule registers (RW, hour*256 + minute)

| Register | Function | Live value | Decoded |
|---|---|---|---|
| 0xE026 | 1-section charge start | 0 | 00:00 |
| 0xE027 | 1-section charge stop | 1536 | 06:00 |
| 0xE028 / 0xE029 | 2-section charge start / stop | 0 / 0 | unused |
| 0xE02A / 0xE02B | 3-section charge start / stop | 0 / 0 | unused |
| 0xE02D / 0xE02E | 1-section discharge start / stop | 0 / 0 | unused |
| 0xE02F / 0xE030 | 2-section discharge start / stop | 0 / 0 | unused |
| 0xE031 / 0xE032 | 3-section discharge start / stop | 0 / 0 | unused |

Encoding: value = hour * 256 + minute. Max 5947 (23*256 + 59 = 23:59). So `1536 = 6*256 + 0 = 06:00`.

Current live config: charge window 1 = 00:00 to 06:00 (off-peak), no scheduled discharge. To do TOU arbitrage, set a discharge window over the peak (18:00 to 24:00 = start 4608, stop 6144-ish, i.e. 24:00 as 23:59 = 6143 or 0).

RTC / current time: `0xE034` (year+month) `0xE035` (day+hour) `0xE036` (minute+second) RW; read via `0x020C/020D`. The inverter's clock must be correct for the schedule to fire at the right wall-clock time - verify it.

## Mode / priority registers (RW)

| Register | Function | Live | Notes |
|---|---|---|---|
| 0xE204 | Output priority | 3 | 0/1/2 documented (2 = hybrid, mains+PV, PV preferred); reads 3 on this unit |
| 0xE20F | Charge priority | (def 2) | 0-3 |
| 0xE216 | Start charge time (hour) | 1 | 01:00, "valid for some custom model" |
| 0xE217 | Start discharge time (hour) | 12 | 12:00, "valid for some custom model" |
| 0xE205 | Mains charge current limit | 80 | x0.1 A? doc says A; range 0-100 |
| 0xE20A | Maximum charge current | 80 | 0-150 |

## Full settings decode (0xE001-0xE039, from V1.7 + live)

Voltage/battery: E002 nominal capacity, E003 system voltage (48), E004 battery type, E005 over-voltage (15.0V), E006 limited-charge (14.4V), E007 equalize, E008 boost/overcharge, E00A boost-return (13.2V-ish), E00B over-discharge-return, E00C under-voltage warn, E00D over-discharge (load cut), E00E limited-discharge, E00F discharge-cutoff SoC (5%), E01B mains-switching voltage, E022 inverter-switching voltage. Times: E010 over-discharge delay (s), E011 equalize time, E012 boost time (min), E023 equalize timeout. The 8 settings the OpenEMS write feature (#53) uses are a subset: E00F, E01C, E01D, E01E, E01F, E020, E205, E20A.

## NOT implemented on this firmware (Illegal data address, confirmed live)

`0xE047-0xE049` timed discharge max power, `0xE04A-0xE04C` timed charge max power, `0xE04D` timed charge source, `0xE400` grid active-power set, `0xE401` PF, `0xE402` reactive, `0xE42A` battery grid participation, `0xE42C` zero-export. So OpenEMS-style instantaneous power dispatch is not available; TOU scheduling is the achievable control.

## What this unlocks for NFE

TOU arbitrage via scheduling: set the charge window to off-peak (already 00:00-06:00) and add a discharge window over the peak tariff, using `0xE026-0xE032`. All RW, all validated readable live. Next: a careful readback-verified live write test of one discharge window (write, verify, restore), then integrate scheduled writes (guarded, like #53) so NFE can shift the battery by tariff without a site visit.

## Method / traceability

Live read-scan via mbpoll (edge + nfe-monitor stopped to free the RS485 bus), firmware v925, 2026-08-09. Decoded against `SRNE_Hybrid_Inverter_MODBUS_protocol_V1.7.pdf` (repo: NFE/CUSTOM_CODE/srne-products). Related: register map (page 126), mbpoll reference (page 125), safe settings write (page 128, #53). Issue logger #67.

# SRNE phase balancing: big consumers on one phase trip the inverter on battery

## Problem

When the site runs on battery (grid outage, typically evening or night), switching on a large single-phase load such as a heater or fan trips the inverter off until the load is removed. This causes an outage for the whole site.

## Evidence (2026-08-11)

Per-phase active power read directly off the SRNE ASP48120SH3 (bus-quiet mbpoll on gw-aaron):

| Phase | On mains (state 2) | On battery (state 3) |
|-------|--------------------|----------------------|
| L1    | 102 W              | 145 W                |
| L2    | 230 W              | 327 W                |
| L3    | 212 W              | 291 W                |
| Total | 544 W              | 763 W                |

L1 consistently carries about half of L2 and L3. Total load is small (under 1 kW against the inverter rating of 12 kW / 24 kVA, roughly 4 kW / 8 kVA per phase), so the trip is not a total-capacity overload. It points to the big consumers being concentrated on one phase: a large load landing on an already heavier phase, plus its switch-on inrush, can overload that single phase or trip protection while the other phases sit nearly idle.

## Action

1. Rebalance customer phase assignments toward an even split. Prefer balancing by measured load rather than by simple 4-3-3 count.
2. Identify the big consumers and move them off the loaded phases (L2 and L3) onto the lighter phase (L1).
3. Re-measure per-phase load after rebalancing to confirm the spread has narrowed.

Use the backup-phase-dashboard phase-balance analysis (reads the customer meter CSVs) to plan the reassignment.

## Also check (a separate, compounding cause)

Protection and power-save settings may make the trip worse on battery. Read (read-only) the power-save level E207, eco mode E20C, overload auto-restart E20D, and overload bypass E212. Off-grid there is no mains to bypass to, so an overload just shuts the inverter down.

## Tracking

GitHub issue: Nearly-Free-Energy/nfe-modbus-energy-logger #70

# OpenEMS Backend InfluxDB Data Model and Edge-ID Collision

> \[!warning\] Verification status  
> **The storage-key collision vulnerability is confirmed in source code, and the repository contains a real configured collision.** However, the vulnerability alone does not prove that Hillary data contaminated the current Sezibwa Pi2 history. Historical causation must be established from production InfluxDB data, connection periods, and gateway logs before any records are rewritten or deleted.

## Executive conclusion

- The configured backend Timedata.InfluxDB component writes edge data into a shared InfluxDB measurement, currently `data`.
- It does not use the complete edge ID as the storage discriminator. It parses the trailing number and stores that number in the OEM edge tag, normally `edge=<number>`.
- Two edge IDs with the same parsed number are indistinguishable to this timedata store and its history queries.
- The repository contains `hillary-test-pi-1` and `aaron-pi-1`; both map to `edge=1`. This is a genuine collision risk.
- The current Sezibwa Pi2 edge definition is `sezibwa-rentals-gw-pi2`, which maps to `edge=2` and does not collide with Hillary.
- `nfetestpi1` is a hostname/deployment user in this repository, not the backend edge ID, and should not be used as evidence of an edge-tag collision.

## Confirmed backend data model

The relevant implementation is:

`io.openems.backend.timedata.influx/src/io/openems/backend/timedata/influx/TimedataInfluxDb.java`

For every accepted data timestamp, the backend constructs an InfluxDB point using:

```
Point.measurement(this.config.measurement())
    .addTag(this.oem.getInfluxdbTag(), String.valueOf(influxEdgeId))
    .time(timestamp, WritePrecision.MS);
```

The deployment configuration sets `measurement="data"`. “Measurement” is the correct InfluxDB term; it is analogous to, but not identical with, a relational database table. All edges handled by this configured timedata provider share that measurement unless another Timedata.InfluxDB instance or measurement is configured.

Channel addresses such as `meter0/ActivePower` and `_sum/EssSoc` are written as fields. History queries parse the requested edge ID through the same numeric function and filter using the resulting numeric tag.

## Confirmed edge-ID parser behavior

`InfluxConnector.parseNumberFromName(edgeId)` uses:

```
\D++(\d++)$
```

This extracts the trailing numeric run rather than preserving the full edge ID:

<table id="bkmrk-edge-id-map"><thead><tr><th>Configured value</th><th>Role in this repository</th><th>Influx tag value</th><th>Finding</th></tr></thead><tbody><tr><td>`hillary-test-pi-1`</td><td>Hillary test edge ID</td><td>`1`</td><td>Collides with `aaron-pi-1`</td></tr><tr><td>`aaron-pi-1`</td><td>Aaron edge ID</td><td>`1`</td><td>Collides with `hillary-test-pi-1`</td></tr><tr><td>`sezibwa-rentals-gw-pi2`</td><td>Current Sezibwa Pi2 edge definition</td><td>`2`</td><td>No suffix collision with Hillary</td></tr><tr><td>`nfetestpi1`</td><td>Hostname/deployment user</td><td>Not applicable as currently configured</td><td>Not the backend edge ID</td></tr></tbody></table>

If an edge ID contains no parseable trailing number, the timedata write is not stored. This is **not completely silent**: `TimedataInfluxDb.writeData()` logs a warning stating that it could not parse the numeric Influx Edge-ID, then returns without writing the notification.

## What a collision does

InfluxDB identifies a point by measurement, tag set, and timestamp. Once two gateways share the same numeric edge tag:

- History queries cannot distinguish which gateway supplied a value.
- Different channel fields can appear together under the same edge series.
- If both gateways write the same field at the same timestamp, later writes can replace or combine with the existing point according to InfluxDB point-update behavior.
- Backend caches keyed by the parsed integer, such as timestamped-channel tracking, can also conflate the two edges.

The resulting history may therefore be mixed, overwritten, or both; “merge” should not be interpreted as guaranteed preservation of every value from both sources.

## What is and is not proven about the incident

**Proven:** the implementation is collision-prone, and two repository edge configurations currently resolve to `edge=1`.

**Not yet proven:** that this caused the reported Hillary-to-Sezibwa contamination. If the affected Sezibwa history was requested under `aaron-pi-1`, the collision is a strong causal candidate. If it was requested under `sezibwa-rentals-gw-pi2`, the `1`-versus-`2` mapping means this specific mechanism does not explain it.

Confirm the affected edge ID and examine production `edge=1` data before finalizing the root-cause statement.

## Immediate containment

1. Inventory every edge registered with or connecting to the production backend.
2. Compute the parsed numeric ID for each and identify duplicates before making changes.
3. Disconnect colliding test rigs from production or assign a globally unique temporary numeric suffix.
4. Back up InfluxDB and the backend/metadata configuration before renaming an edge.
5. Update all coupled references together: metadata, API keys, gateway configuration, monitoring, dashboards, automation, and operational documentation.
6. After each change, verify websocket connectivity, live channels, new timedata writes, history queries, and monitoring alerts.

> \[!note\] Unique numeric suffixes are containment, not the permanent design  
> A naming convention reduces immediate risk but remains brittle and easy to violate as the fleet grows.

## Permanent backend correction

1. Use the complete immutable edge ID as the InfluxDB discriminator, or resolve the edge to another stable, globally unique identifier maintained by backend metadata.
2. Validate uniqueness at edge registration and backend startup. Reject duplicate storage identifiers instead of accepting ambiguous writes.
3. Fail visibly for invalid identifiers, with actionable logs and operational alerts.
4. Add automated tests covering identical suffixes, multi-digit suffixes, IDs without numbers, reconnects, resends, and history-query isolation.
5. Review other structures keyed by the parsed integer, including timestamped-channel tracking and aggregated timedata, so the fix covers more than the point tag.

## Migration requirements

Changing the tag key or value can make existing history unreachable to current queries. The implementation therefore needs an explicit migration plan, such as:

- dual-write the legacy numeric tag and the new full-ID tag for a controlled period;
- support query fallback across both schemas during migration;
- backfill only records that can be attributed confidently;
- retain an immutable backup and a tested rollback path; and
- define a cutover date after which the legacy numeric identity is no longer accepted.

## Historical-data audit before cleanup

1. Identify exactly which logical Sezibwa edge displayed Hillary channels.
2. Determine when `hillary-test-pi-1` and `aaron-pi-1` were simultaneously connected to the same production backend and bucket.
3. Inspect `edge=1` by time range, unique channel inventory, device serial numbers, meter topology, and gateway connection logs.
4. Classify records as confidently Hillary, confidently Aaron/Sezibwa, or ambiguous.
5. Quarantine ambiguous records. Do not delete or rewrite them merely from channel-name assumptions.
6. Document any irrecoverable overlap where the same field and timestamp may have been overwritten.

## Approval boundary

**Approved direction:** immediate containment, a reviewable backend fix, collision tests, and a documented migration design.

**Requires separate approval:** irreversible deletion, reassignment, or rewriting of production historical data. That work must follow the backup and attribution audit above.

# Pre-Commissioning Process for CHINT Meters

## Document Information
- **Version**: 1.0
- **Last Updated**: 2026-04-04
- **Target Audience**: Field Operations Team, Development Team, Remote Commissioning Team

---

## Table of Contents
1. [Introduction](#introduction)
2. [Team Roles and Responsibilities](#team-roles-and-responsibilities)
3. [Equipment and Software Requirements](#equipment-and-software-requirements)
4. [Pre-Commissioning Workflow](#pre-commissioning-workflow)
5. [Converter Tool Guide](#converter-tool-guide)
6. [Troubleshooting Guide](#troubleshooting-guide)
7. [Safety and Best Practices](#safety-and-best-practices)
8. [Inventory Management](#inventory-management)
9. [Future Enhancements](#future-enhancements)

---

## Introduction

### Purpose of Pre-Commissioning

Pre-commissioning is the process of converting CHINT DDSU666/DTSU666 meters from their native **DL/T645 protocol** to **Modbus RTU protocol** and assigning unique Modbus addresses **before** the meters are installed at customer sites.

### Why Pre-Commissioning Matters

**Problem**: Fresh CHINT meters operate on the Chinese DL/T645 protocol and default to Modbus address `1` after conversion. If meters are converted on-site:
- **Address collisions** occur when multiple meters default to address 1
- **Production disruption** happens when using the production USB-RS485 adapter for conversion (interrupts live meters)
- **Field complexity** increases with protocol conversion and addressing at customer locations

**Solution**: Pre-commission all meters in a controlled lab environment before field deployment.

### Benefits

✅ **Zero Downtime**: Field installation becomes plug-and-play (physical connection only)
✅ **No Address Conflicts**: Each meter arrives with unique, pre-assigned Modbus address
✅ **Quality Control**: Test meter communication before shipping
✅ **Simplified Installation**: Field team doesn't need protocol conversion tools
✅ **Audit Trail**: Complete inventory tracking from procurement to commissioning

---

## Team Roles and Responsibilities

### Development Team
**Responsibilities**:
- Assign Modbus addresses based on site requirements and numbering scheme
- Maintain master meter inventory spreadsheet
- Build and distribute converter.exe updates
- Provide escalation support for complex technical issues
- Plan and design system upgrades

**Tools Used**:
- Master Inventory Spreadsheet (Nextcloud Sheets)
- PyInstaller (for building Windows executable)

---

### Field Operations Team
**Responsibilities**:
- Execute lab conversion of meters from DL/T645 → Modbus RTU
- Assign Modbus addresses per Development Team's mapping
- Test meter responses after conversion
- Update inventory status (Assigned → Converted → Shipped)
- Label meters physically with assigned Modbus address
- Package and ship pre-configured meters to sites

**Tools Used**:
- converter.exe (Windows GUI application)
- USB-RS485 adapter (dedicated lab adapter, NOT production)
- Meter Inventory Spreadsheet (Nextcloud Sheets)
- Physical label maker/stickers

**Training Required**:
- Converter tool operation (see [Converter Tool Guide](#converter-tool-guide))
- Inventory management workflow
- Basic RS485 wiring (A+/B- terminals)

---

### Field Installation Team
**Responsibilities**:
- Mount meter at customer location
- Wire power connections (L1/L2/L3/N)
- Wire current transformers (if three-phase meter)
- Connect to existing Modbus RS485 bus (A+/B- terminals)
- Verify meter powers up and displays readings
- Notify Remote Commissioning Team when installation complete

**Tools Used**:
- Standard electrical installation tools
- Multimeter for continuity checks

**Training Required**:
- Meter mounting procedures
- RS485 bus connection (parallel wiring to existing meters)
- Safety protocols for live electrical work

---

### Remote Commissioning Team
**Responsibilities**:
- Connect to Raspberry Pi remotely via ZeroTier + SSH
- Add meter entry to production config file (config.prod.yaml)
- Deploy configuration changes using automated script
- Monitor service restart and verify meter logging
- Update inventory status (Installed → Commissioned)
- Notify stakeholders when meter is live

**Tools Used**:
- ZeroTier VPN client
- SSH client (Terminal, PuTTY, etc.)
- Text editor (nano, vim)
- add_meter.sh CLI helper script (recommended)

**Training Required**:
- SSH basics and remote access
- YAML syntax for meter configuration
- Deployment script usage
- Log monitoring with systemctl/journalctl

---

## Equipment and Software Requirements

### Hardware (Field Operations Team)

| Item | Specification | Purpose | Notes |
|------|--------------|---------|-------|
| **USB-RS485 Adapter** | CH340, FTDI, or PL2303 chipset | Connect Windows PC to meter | **CRITICAL**: Use dedicated lab adapter, NOT production adapter |
| **Windows PC/Laptop** | Windows 7/10/11 | Run converter.exe GUI | Must have USB port |
| **Power Supply** | 230V AC (single-phase) or 3-phase | Power meter during conversion | Match meter type |
| **RS485 Wiring** | 2-wire twisted pair | Connect adapter to meter A+/B- terminals | Keep wiring short (<2 meters) |
| **Label Maker** | Any type | Create Modbus address labels | Physical labels prevent confusion |

### Software (Field Operations Team)

| Item | Location | Version | Purpose |
|------|----------|---------|---------|
| **converter.exe** | Nextcloud: `/Field_Operations/Tools/converter_v1.0.exe` | v1.0 | Protocol conversion and address assignment |
| **USB Driver** | Manufacturer website | Latest | CH340/FTDI/PL2303 driver for Windows |
| **Meter Inventory** | Nextcloud Sheets (shared link) + Excel backup on Nextcloud | Current | Track meter status |

**Download Links**:
- CH340 Driver: [http://www.wch.cn/downloads/CH341SER_EXE.html](http://www.wch.cn/downloads/CH341SER_EXE.html)
- FTDI Driver: [https://ftdichip.com/drivers/vcp-drivers/](https://ftdichip.com/drivers/vcp-drivers/)
- PL2303 Driver: [http://www.prolific.com.tw/US/ShowProduct.aspx?p_id=225](http://www.prolific.com.tw/US/ShowProduct.aspx?p_id=225)

---

## Pre-Commissioning Workflow

### Overview: 5-Phase Process

```
Phase 1: Address Assignment (Development Team)
   ↓
Phase 2: Lab Conversion (Field Operations Team)
   ↓
Phase 3: Pre-Dispatch Testing (Field Operations Team)
   ↓
Phase 4: Field Installation (Field Installation Team)
   ↓
Phase 5: Remote Commissioning (Remote Commissioning Team)
```

---

### Phase 1: Address Assignment (Development Team)

**Duration**: 15-30 minutes per batch

**Steps**:

1. **Receive Procurement List**
   - New meters arrive from supplier
   - Record 12-digit serial numbers from meter labels
   - Note meter types (DDSU666 single-phase or DTSU666 three-phase)

2. **Assign Modbus Addresses**
   - Follow numbering scheme:
     - **Single-phase (DDSU666)**: IDs `02` to `99` (90 meters max per site)
     - **Three-phase (DTSU666)**: IDs `100` and above (unlimited)
   - **CRITICAL RULE**: Never use address `1` (factory default, causes conflicts)

   **Example Assignment**:
   ```
   Site: Office Building A
   - Meter Serial 200322016690 → Address 02 (Floor 1 Reception)
   - Meter Serial 200322016691 → Address 03 (Floor 1 Office)
   - Meter Serial 200322016692 → Address 04 (Floor 2 Office)
   - Meter Serial 200415023456 → Address 100 (Main 3-Phase Supply)
   ```

3. **Update Master Inventory Spreadsheet**
   - Open Nextcloud Sheets inventory (link in team resources)
   - Add new rows for each meter:
     - Meter Serial Number (12 digits)
     - Meter Type (DDSU666 or DTSU666)
     - Site Name
     - Building/Customer Name
     - Assigned Modbus Address
     - Status: **"Assigned"**
     - Date Assigned: Today's date
     - Assigned By: Your name

4. **Send Assignment List to Field Operations Team**
   - Export assignment list as PDF or share Nextcloud Sheets link
   - Include any special instructions (e.g., priority meters, site notes)

---

### Phase 2: Lab Conversion (Field Operations Team)

**Duration**: 5-10 minutes per meter
**Location**: Lab/Office environment
**Tools**: Windows PC, converter.exe, USB-RS485 adapter

**Steps**:

#### 2.1 Physical Setup

1. **Connect Meter to Power**
   - Single-phase: Connect L (live) and N (neutral)
   - Three-phase: Connect L1, L2, L3, and N
   - Verify meter LCD powers on and displays readings

2. **Connect USB-RS485 Adapter**
   - Locate meter's RS485 terminals (usually labeled A+/B- or 485A/485B)
   - Connect adapter's A+ wire to meter's A+ terminal
   - Connect adapter's B- wire to meter's B- terminal
   - **Polarity matters!** Incorrect wiring causes "No response" errors

3. **Connect Adapter to Windows PC**
   - Plug USB end into PC USB port
   - Windows should detect and install driver automatically
   - If not, install driver manually (see Equipment section)

#### 2.2 Launch Converter Tool

1. **Run converter.exe**
   - Double-click converter_v1.0.exe from Nextcloud download
   - GUI window opens with title "DLT645 to Modbus Converter"
   - Initial status shows red "● Disconnected"

#### 2.3 Configure Connection

1. **Detect Serial Port**
   - Click "⟳ Refresh" button
   - Dropdown populates with available ports (e.g., `COM3`, `COM4`)
   - If no ports appear:
     - Check USB cable connection
     - Verify driver installed (Windows Device Manager → Ports)
     - Try different USB port

2. **Select Port and Baud Rate**
   - Select detected port from dropdown (e.g., `COM3`)
   - Baud rate: Keep default `2400` (DLT645 standard)

3. **Connect to Port**
   - Click "Connect" button
   - Status changes to green "● Connected"
   - All action buttons become enabled
   - Log shows: `[HH:MM:SS] Connected → COM3 @ 2400 baud`

#### 2.4 Enter Meter Details

1. **DLT645 Station Address** (12 digits)
   - Find on meter label or LCD display
   - Example: `200322016690`
   - Must be exactly 12 digits (tool validates)

2. **Target Modbus Address** (from assignment list)
   - Refer to Master Inventory for assigned address
   - Example: Address `02` for first single-phase meter
   - Valid range: 1-247 (but avoid address 1)

3. **Reverse Address Bytes** (checkbox)
   - Keep checked by default
   - Tool will auto-retry with this toggled if conversion fails

#### 2.5 Execute Conversion (Recommended: Use "Full Process")

**Option A: Full Process (Recommended for Field Operations)**

1. Click "▶ Full Process" button
2. Tool automatically performs:
   - **Step 1/2**: Convert protocol (DLT645 → Modbus RTU)
   - **Step 2/2**: Change Modbus address to target value
3. Watch log panel for progress:
   ```
   [14:23:15] ═══ Full Process Started ═══
   [14:23:15] [1/2] Converting protocol — station=200322016690
   [14:23:15] TX: FE FE FE FE 68 02 03 20 01 66 90...
   [14:23:27] ✓ Protocol conversion done.
   [14:23:27] [2/2] Changing Modbus address: 1 → 10
   [14:23:30] ✓ Address set to 10.
   [14:23:30] ═══ Full Process Complete ═══
   ```
4. **Success indicators**:
   - ✓ checkmarks for both steps
   - No ✗ errors in log
   - "Full Process Complete" message

**Option B: Manual Step-by-Step** (for troubleshooting)

If Full Process fails, try manual steps:

1. **Convert Protocol First**
   - Click "Convert Protocol" button
   - Tool sends DLT645 protocol-switch command
   - Wait 2-5 minutes for meter to respond
   - Log shows: `✓ Protocol conversion done.`

2. **Scan for Current Address** (optional)
   - Click "🔍 Scan" button
   - Tool tests all 247 Modbus addresses (takes ~90 seconds)
   - Log shows: `✓ Meter found at Modbus address 1`
   - "Current Modbus Address" field auto-updates

3. **Change Address**
   - Ensure "Current Modbus Address" is correct (usually 1 after conversion)
   - Enter "Target Modbus Address" (from assignment list)
   - Click "Change Modbus Addr" button
   - Log shows: `✓ Address changed to 10.`

#### 2.6 Update Inventory

1. **Open Nextcloud Sheets Inventory**
2. **Find meter row** (search by serial number)
3. **Update fields**:
   - Status: Change "Assigned" → **"Converted"**
   - Date Converted: Today's date
   - Converted By: Your name
   - Notes: Add any issues encountered (e.g., "Required reverse byte toggle")

#### 2.7 Label Meter Physically

1. **Create Label** (using label maker or sticker)
   - Text: `Modbus Address: 02` (use actual assigned address)
   - Include site name if space permits
2. **Affix Label to Meter**
   - Place on front panel or top cover
   - Ensure visible after installation
   - Prevents confusion during field installation

#### 2.8 Disconnect and Repeat

1. **Disconnect from Meter**
   - Click "Disconnect" button in converter tool
   - Status returns to red "● Disconnected"
   - Unplug USB-RS485 adapter from PC
   - Disconnect adapter from meter terminals
   - Power off meter

2. **Repeat for Next Meter**
   - Proceed to next meter in batch
   - Follow steps 2.1-2.7 for each meter

---

### Phase 3: Pre-Dispatch Testing (Field Operations Team)

**Duration**: 5 minutes per meter
**Purpose**: Verify meter responds at assigned Modbus address before shipping

**Steps**:

1. **Setup Test Bus**
   - Connect 2-3 converted meters to same RS485 bus
   - Use twisted pair wiring (parallel connection)
   - Ensure meters have different addresses (e.g., 10, 11, 12)

2. **Test Communication** (Manual Method)
   - Connect USB-RS485 adapter to test bus
   - Open converter tool
   - Change baud rate to `9600` (Modbus standard)
   - Use "Scan" function to detect meters
   - Verify each meter responds at its assigned address

3. **Alternative: Use NFE Test Script**
   - If Raspberry Pi available for testing
   - Copy test_modbus_read.py script to test Pi
   - Edit script to test specific meter ID
   - Run: `python3 test_modbus_read.py`
   - Verify readings returned (voltage, current, power)

4. **Record Test Results**
   - Update inventory spreadsheet:
     - Add checkmark or "Tested OK" in Notes column
     - If test fails, mark as "Retest Required" and escalate to Development Team

5. **Package for Shipping**
   - Power off meter
   - Ensure address label is visible
   - Package securely with protective materials
   - Include shipping label with site name

---

### Phase 4: Field Installation (Field Installation Team)

**Duration**: 30-60 minutes per meter (excluding electrical prep)
**Location**: Customer site
**Safety**: Follow all electrical safety protocols

**Steps**:

#### 4.1 Pre-Installation Checks

1. **Verify Meter Received**
   - Confirm meter serial number matches work order
   - Verify Modbus address label matches site plan
   - Inspect for shipping damage

2. **Review Site Plan**
   - Identify installation location
   - Locate existing Modbus RS485 bus terminals
   - Note power source (single-phase or three-phase)

#### 4.2 Physical Installation

1. **Mount Meter** (per manufacturer instructions)
   - Use DIN rail mounting or wall mount bracket
   - Ensure meter is accessible for reading and maintenance
   - Keep away from excessive heat and moisture

2. **Wire Power Connections**

   **Single-Phase (DDSU666)**:
   - Connect Line (L) from customer's circuit breaker
   - Connect Neutral (N) from customer's neutral bar
   - Verify polarity with multimeter

   **Three-Phase (DTSU666)**:
   - Connect L1, L2, L3 from customer's supply
   - Connect Neutral (N) from neutral bar
   - If using current transformers (CTs):
     - Install CTs on each phase conductor
     - Connect CT secondaries to meter CT terminals (K1/L1, K2/L2, K3/L3)
     - Ensure CT orientation matches current flow direction

3. **Wire Modbus RS485 Bus**
   - **CRITICAL**: This step must NOT interrupt existing meters
   - Locate existing RS485 bus terminals (A+/B- or 485A/485B)
   - Connect new meter's A+ terminal to bus A+ (parallel)
   - Connect new meter's B- terminal to bus B- (parallel)
   - Use twisted pair cable (CAT5 or dedicated RS485 cable)
   - Keep total bus length under 1200 meters
   - Use 120Ω termination resistor if meter is at end of bus

#### 4.3 Power-Up and Verify

1. **Energize Meter**
   - Turn on customer circuit breaker
   - Meter LCD should illuminate and display readings
   - Verify voltage readings match expected values (230V ±10% single-phase, 400V ±10% three-phase)

2. **Quick Communication Test** (Optional)
   - If laptop with converter tool available:
     - Connect USB-RS485 adapter to bus (parallel, don't disconnect existing)
     - Set baud rate to 9600
     - Use "Scan" to verify meter responds at assigned address
     - Disconnect adapter when done
   - If no laptop: Skip this step (Remote Commissioning Team will verify)

3. **Notify Remote Commissioning Team**
   - Send message: "Meter [Serial Number] installed at [Site Name], ready for commissioning"
   - Include photo of meter with label visible (for audit trail)
   - Update inventory:
     - Status: "Converted" → **"Installed"**
     - Date Installed: Today's date
     - Installed By: Your name

---

### Phase 5: Remote Commissioning (Remote Commissioning Team)

**Duration**: 10-15 minutes per meter
**Location**: Remote (via ZeroTier VPN + SSH)

**Prerequisites**:
- Receive notification from Field Installation Team
- ZeroTier VPN client installed and connected to network ID: `2873fd00f2d70904`
- SSH access to production Raspberry Pi: `nfetestpi2@10.135.127.86`

**Steps**:

#### 5.1 Connect to Raspberry Pi

1. **Start ZeroTier VPN**
   - Ensure ZeroTier client is running
   - Verify connected to "my-first-network" (ID: 2873fd00f2d70904)
   - Check ZeroTier shows "ONLINE" status

2. **SSH to Production Pi**
   ```bash
   ssh nfetestpi2@10.135.127.86
   ```
   - Enter password when prompted
   - Or use SSH key if configured (passwordless)

#### 5.2 Add Meter to Configuration (Option A: Manual Edit)

**For users comfortable with YAML editing**:

1. **Edit Staging Config**
   ```bash
   nano ~/nfe-modbus-energy-logger/config/config.prod.yaml
   ```

2. **Add Meter Entry**

   Scroll to the `meters:` section and add new entry:

   **Single-Phase Meter Example**:
   ```yaml
   meters:
     # ... existing meters ...

     - id: 2                      # Assigned Modbus address
       name: "floor1_reception"    # Descriptive name (lowercase, underscores)
       type: "1phase"              # Meter type
       enabled: true               # Enable logging
   ```

   **Three-Phase Meter Example**:
   ```yaml
   meters:
     # ... existing meters ...

     - id: 100                     # Assigned Modbus address
       name: "main_supply"         # Descriptive name
       type: "3phase"              # Meter type
       enabled: true               # Enable logging
   ```

   **Naming Conventions**:
   - Use lowercase letters
   - Use underscores instead of spaces
   - Make names descriptive but concise
   - Examples: `floor2_office`, `hvac_panel`, `server_room`

3. **Save and Exit**
   - Press `Ctrl+O` to save
   - Press `Enter` to confirm filename
   - Press `Ctrl+X` to exit nano

#### 5.2 Add Meter to Configuration (Option B: CLI Helper Script - RECOMMENDED)

**For automated validation and safety**:

1. **Run Helper Script**
   ```bash
   ~/nfe-modbus-energy-logger-prod/scripts/add_meter.sh
   ```

2. **Answer Interactive Prompts**
   ```
   Enter Meter ID (2-247): 2
   Enter Meter Name: floor1_reception
   Enter Meter Type (1phase/3phase): 1phase
   Enable meter? (yes/no): yes

   About to add:
     ID: 2
     Name: floor1_reception
     Type: 1phase
     Enabled: true

   Proceed? (yes/no): yes
   ```

3. **Script Automatically**:
   - Validates input (address range, type, duplicate ID check)
   - Backs up current config
   - Appends meter to YAML
   - Runs deployment script
   - Monitors service restart
   - Verifies meter logging
   - Reports success or failure

4. **Review Output**
   ```
   ✅ Meter 2 (floor1_reception) successfully added and logging
   📁 Data directory: ~/nfe-modbus-energy-logger-prod/data/meter_010/
   📊 CSV file: meter_010_2026-04-04.csv
   ```

#### 5.3 Deploy to Production (Manual Method Only)

**Skip this if you used add_meter.sh script (already done)**

1. **Run Deployment Script**
   ```bash
   ~/nfe-modbus-energy-logger/scripts/deploy.sh
   ```

2. **Script Actions**:
   - Backs up production directory
   - Syncs staging code to production
   - Runs pre-flight test (30-second dry run)
   - Restarts meter.service
   - Verifies service started successfully
   - Auto-rollback if service fails

3. **Monitor Deployment**
   - Watch for "Deployment complete" message
   - Check for any error messages
   - If errors occur, script auto-rolls back

#### 5.4 Monitor Service Restart

1. **Watch Service Logs**
   ```bash
   sudo journalctl -u meter.service -f
   ```

2. **Look for Meter Initialization**
   ```
   [timestamp] ✅ Initialized meter 10 (floor1_reception, 1phase)
   [timestamp] 🚀 Starting multi-meter logger
   [timestamp]    Poll interval: 10s
   [timestamp]    Log interval: 900s (15 minutes)
   [timestamp]    Active meters: 3
   ```

3. **Press `Ctrl+C` to stop watching logs**

#### 5.5 Verify Meter Logging

1. **Check Data Directory Created**
   ```bash
   ls -lh ~/nfe-modbus-energy-logger-prod/data/
   ```
   - Should show new directory: `meter_010/` (or corresponding ID)

2. **Check CSV File Started**
   ```bash
   ls -lh ~/nfe-modbus-energy-logger-prod/data/meter_010/
   ```
   - Should show CSV file: `meter_010_2026-04-04.csv` (today's date)

3. **View Recent Log Entries**
   ```bash
   tail -20 ~/nfe-modbus-energy-logger-prod/data/meter_010/meter_010_2026-04-04.csv
   ```
   - Should show recent readings with timestamps
   - Verify data fields populated (not all zeros or empty)

4. **Sample Output**:
   ```
   timestamp,meter_id,V_L1_V,I_L1_A,P_total_kW,E_total_kWh,...
   2026-04-04 15:15:00,10,234.5,2.1,0.49,12345.6,...
   2026-04-04 15:30:00,10,235.1,2.3,0.53,12345.8,...
   ```

#### 5.6 Update Inventory and Notify

1. **Update Inventory Spreadsheet**
   - Status: "Installed" → **"Commissioned"**
   - Date Commissioned: Today's date
   - Commissioned By: Your name
   - Notes: Add any observations (e.g., "All readings nominal")

2. **Verify Backup Enabled** (if configured)
   - Check backup service runs successfully:
     ```bash
     sudo journalctl -u backup.service -n 50
     ```
   - Verify meter CSV files being backed up to Nextcloud

3. **Notify Stakeholders**
   - Send confirmation message: "Meter [Serial Number] commissioned at [Site Name] - logging active"
   - Include link to meter data directory or dashboard (if available)

---

## Converter Tool Guide

### GUI Overview

```
┌─────────────────────────────────────────────────────────┐
│  DLT645 to Modbus Converter                             │
├─────────────────────────────────────────────────────────┤
│  Serial Port: [COM3         ▼] [⟳ Refresh]  [Connect]  │
│  Baud Rate:   [2400         ▼]                          │
│  Status: ● Connected                                     │
├─────────────────────────────────────────────────────────┤
│  DLT645 Station Address (12 digits):                    │
│  [200322016690                                       ]  │
│                                                           │
│  Current Modbus Address: [1   ]  [🔍 Scan]              │
│  Target Modbus Address:  [10  ]                         │
│                                                           │
│  ☑ Reverse address bytes                                │
├─────────────────────────────────────────────────────────┤
│  [Convert Protocol] [Change Modbus Addr] [▶ Full Process]│
├─────────────────────────────────────────────────────────┤
│  Log Panel (scrollable):                                │
│  [14:23:15] Connected → COM3 @ 2400 baud                │
│  [14:23:25] Converting protocol — station=200322016690  │
│  [14:23:27] ✓ Protocol conversion done.                 │
│  [14:23:30] ✓ Address changed to 10.                    │
│                                                           │
└─────────────────────────────────────────────────────────┘
```

### Input Field Descriptions

| Field | Description | Valid Values | Example |
|-------|-------------|--------------|---------|
| **Serial Port** | USB-RS485 adapter COM port | Auto-detected ports | COM3 |
| **Baud Rate** | Communication speed | 1200, 2400, 4800, 9600, 19200 | 2400 (DLT645 default) |
| **DLT645 Station Address** | Meter's 12-digit serial number | 000000000000 - 999999999999 | 200322016690 |
| **Current Modbus Address** | Address meter currently responds to | 1-247 | 1 (factory default) |
| **Target Modbus Address** | New address to assign | 1-247 | 10 (from assignment list) |
| **Reverse Address Bytes** | Toggle byte order for firmware compatibility | Checked/Unchecked | ☑ Checked (recommended) |

### Button Functions

| Button | Function | When to Use | Duration |
|--------|----------|-------------|----------|
| **⟳ Refresh** | Re-scan for serial ports | USB adapter just connected | Instant |
| **Connect** | Open selected serial port | Before any conversion operations | Instant |
| **Disconnect** | Close serial port | After conversion complete | Instant |
| **Convert Protocol** | Send DLT645 protocol-switch command | Standalone protocol conversion | 2-5 minutes |
| **🔍 Scan** | Search all 247 Modbus addresses | Find current meter address | ~90 seconds |
| **Change Modbus Addr** | Write new address to meter | After protocol conversion | 5-10 seconds |
| **▶ Full Process** | Automated conversion + address change | **RECOMMENDED for Field Operations** | 5-10 minutes |

### Success Indicators

**Look for these in the log panel**:

✅ **Protocol Conversion Success**:
```
[14:23:27] ✓ Protocol conversion done.
```

✅ **Address Change Success**:
```
[14:23:30] ✓ Address set to 10.
```

✅ **Full Process Success**:
```
[14:23:30] ═══ Full Process Complete ═══
```

✅ **Meter Discovery Success**:
```
[14:23:45] ✓ Meter found at Modbus address 1. 'Current Modbus Address' updated.
```

### Error Indicators

❌ **Communication Errors**:
```
[14:23:27] ✗ No response — check wiring / address / baud rate.
```

❌ **Validation Errors**:
```
Validation Error: Station address must be exactly 12 digits.
Validation Error: Modbus address must be an integer 1–247.
```

❌ **Port Errors**:
```
Error: No port selected. Click ⟳ Refresh first.
Connection Error: [SerialException message]
```

---

## Troubleshooting Guide

### Problem: No Serial Ports Detected

**Symptoms**:
- Dropdown shows "No ports found" or is empty
- "⟳ Refresh" button doesn't populate ports

**Causes and Solutions**:

1. **USB Adapter Not Connected**
   - ✅ **Solution**: Plug USB adapter into PC USB port
   - Click "⟳ Refresh" again

2. **Driver Not Installed**
   - ✅ **Solution**: Install USB-RS485 driver for your adapter chipset
   - Check Windows Device Manager → Ports (COM & LPT)
   - If device shows yellow warning icon, driver missing
   - Download and install correct driver (see Equipment section)
   - Restart PC if required
   - Click "⟳ Refresh" after driver installed

3. **Faulty USB Cable or Adapter**
   - ✅ **Solution**: Try different USB port
   - Try different USB cable
   - Test adapter on another PC
   - Replace adapter if confirmed faulty

4. **Windows Security Blocking**
   - ✅ **Solution**: Run converter.exe as Administrator
   - Right-click → "Run as administrator"

---

### Problem: "No Response" During Protocol Conversion

**Symptoms**:
- Log shows: `[HH:MM:SS] ✗ No response.`
- Tool retries with reverse byte toggle automatically

**Causes and Solutions**:

1. **Incorrect Station Address**
   - ✅ **Solution**: Double-check 12-digit serial number on meter label
   - Ensure no typos (easy to confuse 0/O, 1/I, 6/8)
   - Verify number matches meter (not packaging)

2. **Wiring Problem (Most Common)**
   - ✅ **Solution**: Check RS485 connections
   - Verify A+ to A+, B- to B- (not swapped)
   - Tighten terminal screws (loose connections cause intermittent failures)
   - Use twisted pair cable (not individual wires)
   - Keep wiring short (<2 meters)

3. **Incorrect Baud Rate**
   - ✅ **Solution**: Confirm baud rate is 2400 for DLT645 meters
   - Some meters may use different rates (try 1200, 4800)

4. **Meter Not Powered**
   - ✅ **Solution**: Verify meter LCD is illuminated
   - Check power connections (L/N for single-phase, L1/L2/L3/N for three-phase)
   - Use multimeter to verify voltage at terminals

5. **RS485 Bus Termination Issue**
   - ✅ **Solution**: If multiple meters on same bus, add 120Ω termination resistor across A+/B- at each end

6. **Reverse Byte Order Required**
   - ✅ **Solution**: Tool auto-retries with reverse toggle
   - Manually toggle "Reverse address bytes" checkbox and retry

7. **Meter Already in Modbus Mode**
   - ✅ **Solution**: Meter may already be converted (from previous attempt)
   - Change baud rate to 9600
   - Use "Scan" function to find current address
   - Skip to "Change Modbus Addr" step if needed

---

### Problem: Scan Finds No Modbus Address

**Symptoms**:
- After protocol conversion, scan completes but finds no meter
- Log shows: `⚠ No meter responded on Modbus addresses 1-247.`

**Causes and Solutions**:

1. **Protocol Conversion Failed**
   - ✅ **Solution**: Meter still in DLT645 mode
   - Return to "Convert Protocol" step
   - Try manual conversion with longer timeout
   - Power cycle meter (turn off, wait 10 seconds, turn on)
   - Retry conversion

2. **Incorrect Baud Rate for Modbus**
   - ✅ **Solution**: After conversion, meter uses 9600 baud for Modbus
   - Change baud rate dropdown to 9600
   - Retry scan

3. **Meter Needs Time to Restart**
   - ✅ **Solution**: Wait 5 minutes after protocol conversion
   - Power cycle meter
   - Retry scan

---

### Problem: Address Change Fails

**Symptoms**:
- Log shows: `✗ Address change failed.`
- Meter doesn't respond at new address

**Causes and Solutions**:

1. **Wrong Register Address for Meter Type**
   - ✅ **Solution**:
   - DDSU666 (single-phase) uses register 0x0006
   - DTSU666 (three-phase) uses register 0x002E
   - Converter GUI currently supports single-phase only
   - For three-phase, use CLI version:
     ```bash
     python3 converter_cli.py change --port COM3 --current 1 --target 10 --type 3phase
     ```

2. **Meter Not in Modbus Mode**
   - ✅ **Solution**: Ensure protocol conversion succeeded first
   - Use "Scan" to verify meter responds in Modbus mode

3. **Current Address Incorrect**
   - ✅ **Solution**: Use "Scan" function to discover actual current address
   - Update "Current Modbus Address" field with scanned value
   - Retry address change

---

### Problem: Meter Doesn't Respond After Conversion

**Symptoms**:
- Conversion appears successful in log
- But meter doesn't respond in Modbus mode later

**Causes and Solutions**:

1. **Conversion Incomplete (False Positive)**
   - ✅ **Solution**: Some meters acknowledge command but don't actually switch
   - Power cycle meter (off for 30 seconds, then on)
   - Wait 5 minutes after power-on
   - Retry scan

2. **Firmware Requires Extended Timing**
   - ✅ **Solution**: Use CLI version with extended timeout:
     ```bash
     python3 converter_cli.py convert --port COM3 --station 200322016690 --reverse --extended
     ```

3. **Meter Reverted to DLT645 Mode**
   - ✅ **Solution**: Some meters revert to factory default after power loss
   - This is rare but possible
   - Repeat full conversion process
   - Test immediately after conversion before power cycling

---

### Escalation: When to Contact Development Team

Contact Development Team if:
- Meter doesn't respond after 3 conversion attempts
- Error messages not covered in this guide
- Physical damage suspected (meter LCD dead, RS485 terminals broken)
- Firmware version incompatibility suspected
- Need CLI script for three-phase meter address change
- converter.exe crashes or freezes

**Escalation Information to Provide**:
- Meter serial number
- Meter type (DDSU666 or DTSU666)
- Complete log output from converter tool (screenshot)
- Steps already attempted
- Observations (LCD displays, unusual behavior)

---

## Safety and Best Practices

### General Safety

⚠️ **Electrical Safety**:
- Only qualified electricians perform power wiring (Phase 4)
- De-energize circuits before connecting meter to live power
- Use lockout/tagout (LOTO) procedures
- Verify voltage with multimeter before assuming power is off
- Wear appropriate personal protective equipment (PPE)

⚠️ **RS485 Bus Safety**:
- Never connect/disconnect RS485 wiring with power applied (can damage meter)
- Use ESD (electrostatic discharge) precautions when handling meter electronics
- Keep RS485 bus wiring away from high-voltage conductors (>50V)

### Conversion Best Practices

✅ **One Meter at a Time**:
- Convert meters individually (don't connect multiple unconverted meters to same bus)
- This prevents address conflicts during conversion

✅ **Document Before Converting**:
- Update inventory BEFORE starting conversion
- Record meter serial number, type, and assigned address
- This prevents confusion if interrupted mid-process

✅ **Test Before Shipping**:
- Always perform Phase 3 Pre-Dispatch Testing
- Catch issues in lab, not at customer site
- Reduces field failures and rework

✅ **Never Reuse Addresses on Same Site**:
- Each meter must have unique address
- Keep site-specific address map
- Even if meter replaced, don't reuse old address immediately (wait until removed from config)

✅ **Physical Labeling is Mandatory**:
- Label prevents installation errors
- Field Installation Team relies on label (may not have inventory access)
- Use durable labels (water-resistant, doesn't fade)

✅ **Keep Conversion Logs**:
- Take screenshot of successful conversion log
- Store in Nextcloud or local folder
- Useful for audit trail and troubleshooting
- Include meter serial number in filename (e.g., `conversion_200322016690_success.png`)

---

## Inventory Management

### Master Inventory Spreadsheet

**Primary Location**: Nextcloud Sheets (shared link - request from Development Team)
**Backup Location**: Nextcloud `/Field_Operations/Templates/METER_INVENTORY_TEMPLATE.xlsx`

### Required Columns

| Column Name | Data Type | Purpose | Example |
|-------------|-----------|---------|---------|
| **Meter Serial Number** | Text (12 digits) | Unique meter identifier | 200322016690 |
| **Meter Type** | Text | Single or three-phase | DDSU666 or DTSU666 |
| **Site Name** | Text | Customer site | Office Building A |
| **Building/Customer** | Text | Specific location or customer name | Floor 1 Reception |
| **Assigned Modbus Address** | Number (1-247) | Pre-assigned unique address | 10 |
| **Status** | Dropdown | Current workflow stage | Assigned, Converted, Shipped, Installed, Commissioned |
| **Date Assigned** | Date | When address assigned | 2026-04-01 |
| **Date Converted** | Date | When protocol conversion completed | 2026-04-02 |
| **Date Installed** | Date | When physically installed at site | 2026-04-03 |
| **Date Commissioned** | Date | When added to NFE config and logging | 2026-04-04 |
| **Converted By** | Text | Field Ops team member name | Jane Doe |
| **Installed By** | Text | Field Installation team member | John Smith |
| **Commissioned By** | Text | Remote Commissioning team member | Alice Johnson |
| **Notes** | Text | Issues, observations, special instructions | Required reverse byte toggle |

### Status Workflow

```
Unassigned → Assigned → Converted → Shipped → Installed → Commissioned
     ↓          ↓           ↓           ↓          ↓            ↓
   (New)   (Dev Team)  (Field Ops) (Field Ops) (Field Inst) (Remote Comm)
```

**Status Definitions**:

- **Unassigned**: New meter received from supplier, no address assigned yet
- **Assigned**: Development Team assigned Modbus address, ready for conversion
- **Converted**: Field Operations Team completed protocol conversion and address assignment
- **Shipped**: Meter packaged and sent to customer site
- **Installed**: Field Installation Team physically installed meter and wired to bus
- **Commissioned**: Remote Commissioning Team added to NFE config and verified logging

### Conditional Formatting (Nextcloud Sheets)

**Setup in Nextcloud Sheets**:

1. **Status Column Color Coding**:
   - Unassigned: Gray background
   - Assigned: Yellow background (action required by Field Ops)
   - Converted: Light blue (ready to ship)
   - Shipped: Blue (in transit)
   - Installed: Orange (action required by Remote Comm)
   - Commissioned: Green (complete)

2. **Overdue Highlighting**:
   - If "Status = Assigned" and "Date Assigned" > 7 days ago → Red text (conversion overdue)
   - If "Status = Installed" and "Date Installed" > 2 days ago → Red text (commissioning overdue)

3. **Address Range Validation**:
   - If "Meter Type = DDSU666" and "Assigned Modbus Address" < 10 or > 99 → Red background (invalid)
   - If "Meter Type = DTSU666" and "Assigned Modbus Address" < 100 → Red background (invalid)

### Data Validation (Nextcloud Sheets)

**Setup in Nextcloud Sheets**:

1. **Status Dropdown**:
   - Column: Status
   - Criteria: List from a range: `Unassigned, Assigned, Converted, Shipped, Installed, Commissioned`
   - Reject invalid input

2. **Meter Type Dropdown**:
   - Column: Meter Type
   - Criteria: List from a range: `DDSU666, DTSU666`
   - Reject invalid input

3. **Address Range Validation**:
   - Column: Assigned Modbus Address
   - Criteria: Number between 1 and 247
   - Warning on invalid input (not rejection, to allow temporary placeholders)

### Audit Trail Requirements

**What to Track**:
- Every status change must include date and operator name
- Notes column should capture any deviations from standard process
- Conversion logs (screenshots) stored in Nextcloud with meter serial in filename

**Retention**:
- Keep inventory records for lifetime of deployment
- Archive old entries when meters decommissioned
- Export monthly backup to Excel and store in Nextcloud

---

## Future Enhancements

**Planned for Phase 2**:

1. **Web-Based Commissioning Portal**
   - Browser-based UI for adding meters to NFE config
   - No SSH required for Remote Commissioning Team
   - Authentication and audit logging
   - Real-time dashboard showing meter status

2. **Automated Meter Discovery on Modbus Bus**
   - Raspberry Pi scans bus for new meters automatically
   - Suggests config entries for detected meters
   - Reduces manual configuration errors

3. **Inventory Management Database**
   - Centralized database replacing Nextcloud Sheets
   - API integration between converter tool and inventory
   - Auto-update status on successful conversions
   - Real-time sync across all teams

4. **Converter Tool Enhancements**:
   - Batch operations (convert multiple meters in sequence)
   - Save/load meter assignment lists
   - Auto-populate from inventory database
   - Persistent configuration (remember last settings)
   - Auto-generated conversion reports (PDF)

5. **Mobile App for Field Installation**
   - Scan meter barcode/QR code
   - Verify address label matches inventory
   - Guided installation checklist
   - Photo documentation for audit trail

6. **Automated Alerting**:
   - Notify Remote Commissioning when meter installed
   - Alert if meter stops logging after commissioning
   - Daily summary of meters pending action

7. **Fleet Management Dashboard**:
   - Web dashboard showing all meters across all sites
   - Real-time status (online/offline)
   - Energy consumption graphs
   - Maintenance scheduling

**How to Request Features**:
- Contact Development Team (CTO)
- Describe use case and priority
- Features prioritized based on team feedback and ROI

---

## Appendix

### Glossary

- **DL/T645**: Chinese national standard for electrical meter communication protocol
- **Modbus RTU**: Industry-standard serial communication protocol for industrial devices
- **RS485**: Differential serial communication standard (A+/B- or Data+/Data-)
- **Station Address**: 12-digit unique identifier for DL/T645 meters (meter serial number)
- **Modbus Slave Address**: 1-byte address (1-247) for Modbus devices on same bus
- **USB-RS485 Adapter**: Device converting USB to RS485 differential signals
- **Baud Rate**: Communication speed in bits per second (bps)
- **Protocol Conversion**: One-time operation switching meter from DL/T645 to Modbus mode
- **ZeroTier**: Virtual private network (VPN) software for secure remote access
- **SSH**: Secure Shell protocol for remote command-line access

### Quick Reference Card

**Converter Tool Quick Steps**:
1. Connect meter power and USB-RS485 adapter
2. Run converter.exe → Refresh → Select port → Connect
3. Enter 12-digit station address (from meter label)
4. Enter target Modbus address (from inventory)
5. Click "▶ Full Process"
6. Wait for "✓ Full Process Complete"
7. Update inventory status to "Converted"
8. Label meter with address sticker

**Common Mistakes to Avoid**:
- ❌ Using address 1 (always use 10+ for single-phase, 100+ for three-phase)
- ❌ Swapping A+/B- wiring (causes "No response" errors)
- ❌ Forgetting to change baud rate to 9600 after conversion (for Modbus scan)
- ❌ Skipping physical label (causes installation errors)
- ❌ Not updating inventory (breaks audit trail)
---

**Document Version History**:
- v1.0 (2026-04-04): Initial release - Complete pre-commissioning workflow

**Document Owner**: Development Team
**Review Cycle**: Quarterly or as needed for process updates

# Towards a Framework for Autonomous Microgrids

# Table of Contents

1. Introduction
2. Core Concepts
    
    
    - Assets
    - Foundational Capabilities
    - Application Capabilities
3. Automation vs Autonomy
4. Levels of Operational Autonomy
    
    
    - Level 1 — Manual Local Operation
    - Level 2 — Automated Supervisory Control
    - Level 3 — Autonomous Supervisory Control
5. Operational Criticality
    
    
    - Safety-Critical Capabilities
    - Business-Critical Capabilities
    - Optimization Capabilities
6. Applying the Framework
7. Implications for a Microgrid OS

## A picture is worth a thousand words 

[![Microgrid Capability Framework.png](https://bookstack.nearlyfreeenergy.com/uploads/images/gallery/2026-05/scaled-1680-/microgrid-capability-framework.png)](https://bookstack.nearlyfreeenergy.com/uploads/images/gallery/2026-05/microgrid-capability-framework.png)

## Introduction

As distributed energy resources become increasingly software-defined, microgrids are evolving from manually operated electrical systems into digitally coordinated energy platforms. This evolution creates a need for a clear framework describing the degree of operational autonomy assigned to different microgrid functions.

This document proposes a simple three-level autonomy model for microgrids inspired by concepts from industrial automation, supervisory control systems, and autonomous systems engineering.

Unlike autonomous vehicle frameworks that classify an entire vehicle into a single automation level, this framework applies autonomy levels to specific operational capabilities operating on specific assets.

For example:

- Observing smart meter consumption
- Steering battery dispatch
- Observing EV charger utilization
- Steering flexible loads
- Forecasting solar production

Each capability may operate at a different level of autonomy.

A microgrid could therefore simultaneously contain:

- Level 3 autonomous battery steering
- Level 2 remote EV charger steering
- Level 1 manual generator operation

This capability-oriented approach allows microgrids to evolve incrementally toward higher levels of operational autonomy.

---

# Core Concepts

## Assets

Assets are physical, digital, or economic components participating in the operation of the microgrid.

This framework groups assets into three primary categories.

### 1. Physical Assets

Physical assets are hardware systems that generate, store, distribute, consume, or protect electrical energy.

Examples include:

- Smart meters
- Battery energy storage systems (BESS)
- Solar PV inverters
- EV chargers
- Diesel generators
- Protection relays
- Flexible loads
- Distribution transformers
- Remote disconnect relays

### 2. Digital Assets

Digital assets are software systems, communications systems, and computational services used to monitor, coordinate, optimize, and operate the microgrid.

Examples include:

- Billing systems
- Tariff engines
- Payment systems
- Forecasting systems
- Customer identity systems
- AI orchestration systems
- SCADA platforms
- DERMS platforms
- Telemetry databases
- Mobile applications
- Notification systems

### 3. Economic and Contractual Assets

Economic and contractual assets represent the financial, commercial, and policy relationships governing the microgrid.

Examples include:

- Customer accounts
- Energy credits
- Tariff structures
- Power purchase agreements (PPAs)
- Service tiers
- Demand response agreements
- Payment obligations
- Credit limits
- Utility interconnection agreements

These asset categories recognize that modern microgrids are not purely electrical systems. They are virtual-physical-economic systems integrating energy infrastructure, software platforms, and operational business logic into a unified operational environment.

---

## Foundational Capabilities

Foundational capability domains are the core operational primitives from which higher-order microgrid behaviors and applications are constructed.

Rather than treating every operational function as a separate foundational capability, this framework identifies a small set of core capabilities that can be composed together to create more advanced orchestration, optimization, commercial, and autonomous behaviors.

These foundational domains operate across physical, digital, and economic assets.

### 1. Observability

Observability capabilities measure, record, analyze, and communicate system state.

Observability forms the awareness layer of the microgrid.

Examples:

- Reading smart meter consumption
- Monitoring battery state of charge
- Detecting inverter faults
- Measuring feeder voltage and frequency
- Monitoring EV charging sessions
- Customer usage analytics
- Payment status monitoring
- Event logging and telemetry collection

### 2. Steering

Steering capabilities execute operational actions intended to guide system behavior toward desired operational outcomes.

Unlike traditional low-level control systems, steering emphasizes adaptive orchestration, policy-driven operation, and outcome-oriented system management across distributed assets.

Steering forms the action layer of the microgrid.

Examples:

- Disconnecting a load
- Dispatching battery storage
- Curtailing solar generation
- Starting a backup generator
- Setting EV charging limits
- Executing demand response actions
- Remote relay switching
- Service disconnection and reconnection

### 3. Intelligence

Intelligence capabilities generate predictions, recommendations, classifications, reasoning, and adaptive operational decisions.

Intelligence forms the reasoning layer of the microgrid.

Examples:

- Solar production forecasting
- Load forecasting
- Predictive maintenance
- Fault prediction
- Fraud detection
- Adaptive operational policy selection
- AI-driven energy management
- Anomaly detection
- Optimization modeling

### 4. Governance

Governance capabilities define and enforce operational rules, permissions, priorities, compliance requirements, and safety boundaries.

Governance forms the constitutional layer of the microgrid.

Examples:

- Access control
- Human override policies
- Safety constraints
- Regulatory compliance
- Escalation policies
- Operational audit logging
- Cybersecurity enforcement
- Service disconnection policies
- Critical load protections

---

## Application Capabilities

Operational application domains are higher-order business and operational functions constructed from combinations of the foundational capabilities.

These applications are not themselves foundational primitives. Rather, they emerge from orchestrating observability, steering, intelligence, and governance capabilities together.

### Coordination

Coordination capabilities orchestrate workflows across systems, users, assets, and operational processes.

Coordination typically combines:

- Observability
- Steering
- Governance

Examples:

- Human escalation workflows
- Multi-device orchestration
- Customer notification systems
- Utility coordination
- Maintenance scheduling
- Service provisioning workflows
- Incident response coordination

### Optimization

Optimization capabilities improve operational efficiency, economics, reliability, or customer experience.

Optimization typically combines:

- Intelligence
- Steering

Examples:

- Energy arbitrage optimization
- EV charging optimization
- Demand response coordination
- Forecast-driven battery dispatch
- Load balancing
- Power quality optimization
- Asset utilization optimization

### Commercial Operations

Commercial operations capabilities manage the economic and business functions of the microgrid.

Commercial operations typically combine:

- Observability
- Steering
- Intelligence
- Governance

Examples:

- Customer billing
- Tariff management
- Payment processing
- Credit management
- Revenue collection
- Energy credit accounting
- Invoice generation
- Service eligibility evaluation
- Automated service disconnection and reconnection

---

# Automation vs Autonomy

The distinction between automation and autonomy is foundational to this framework.

## Automation

Automation refers to systems that execute predefined instructions or workflows under human-defined logic.

Examples:

- Fixed battery charging schedules
- Rule-based generator startup
- Threshold-based load shedding
- Remote switching by operators
- Scheduled EV charger limits

An automated system follows instructions.

## Autonomy

Autonomy refers to systems capable of independently managing operational objectives under changing conditions while operating within defined technical, economic, and safety constraints.

Examples:

- Optimizing battery dispatch based on tariffs, weather forecasts, and outage probability
- Dynamically prioritizing critical loads during constrained operation
- Coordinating EV charging across multiple users to minimize peak demand
- Predictive fault response and recovery
- Adaptive energy management based on real-time conditions

An autonomous system manages outcomes.

---

# Levels of Operational Autonomy

This framework distinguishes between:

- Manual local operation
- Automated supervisory control
- Autonomous supervisory control

---

## Level 1 — Manual Local Operation

At Level 1, foundational capabilities are operated directly by humans physically present at the asset location.

The asset itself provides the operational interface.

Examples:

- Reading values directly from a smart meter display
- Manually operating breakers or disconnects
- Physically starting a generator
- Local inverter configuration
- On-site battery inspection

### Operational Characteristics

<table id="bkmrk-question-answer-who-"><thead><tr><th>Question</th><th>Answer</th></tr></thead><tbody><tr><td>Who monitors the system?</td><td>Human operators on-site</td></tr><tr><td>Who makes decisions?</td><td>Human operators on-site</td></tr><tr><td>Who executes actions?</td><td>Human operators on-site</td></tr><tr><td>Who handles failures?</td><td>Human operators on-site</td></tr></tbody></table>

### Characteristics

- No remote supervisory capability
- Human-driven operational awareness
- Minimal software orchestration
- Typically isolated or standalone systems

### Relevant Standards

Relevant standards may include:

- IEEE 1547 for DER interconnection behavior
- IEEE 2030.7 for microgrid controller functional specification
- IEC 61850 for power system communication models

At Level 1, however, most operational authority remains local and manual.

---

## Level 2 — Automated Supervisory Control

At Level 2, foundational capabilities are supervised remotely through software platforms and communications networks.

Humans remain responsible for operational decisions, while software automates telemetry collection, visualization, alarms, workflows, and execution of predefined control logic.

Examples:

- Remote smart meter monitoring
- SCADA-based microgrid supervision
- Rule-based battery dispatch
- Remote EV charger management
- Automated threshold alarms
- Scheduled load control

### Operational Characteristics

<table id="bkmrk-question-answer-who--1"><thead><tr><th>Question</th><th>Answer</th></tr></thead><tbody><tr><td>Who monitors the system?</td><td>Human operators remotely</td></tr><tr><td>Who makes decisions?</td><td>Human operators remotely</td></tr><tr><td>Who executes actions?</td><td>Automated systems under human-defined logic</td></tr><tr><td>Who handles failures?</td><td>Human operators with software assistance</td></tr></tbody></table>

### Characteristics

- Remote visibility and control
- Centralized supervisory software
- Deterministic rule-based workflows
- Human approval remains central
- Software improves operational efficiency but does not independently manage system objectives

### Relevant Standards

This level aligns closely with existing industrial automation and microgrid supervisory standards including:

- IEEE 2030.7 — Specification of Microgrid Controllers
- IEEE 2030.8 — Testing of Microgrid Controllers
- IEC 61850 — Power system communication models
- DNP3 and Modbus — Telemetry and control protocols
- OpenADR — Demand response coordination

Level 2 corresponds closely to modern SCADA and DERMS architectures.

---

## Level 3 — Autonomous Supervisory Control

At Level 3, foundational capabilities are operated autonomously by software systems capable of independently managing operational objectives within defined technical, economic, and safety constraints.

Humans define policies, operating boundaries, escalation procedures, and override authority, but the system continuously makes operational decisions without requiring constant human supervision.

Examples:

- AI-driven battery optimization
- Autonomous load orchestration
- Dynamic outage response
- Self-optimizing EV charging coordination
- Predictive maintenance actions
- Autonomous islanding and reconnection
- Adaptive tariff-aware energy management

### Operational Characteristics

<table id="bkmrk-question-answer-who--2"><thead><tr><th>Question</th><th>Answer</th></tr></thead><tbody><tr><td>Who monitors the system?</td><td>Autonomous software systems with human oversight</td></tr><tr><td>Who makes decisions?</td><td>Autonomous systems operating within defined policies</td></tr><tr><td>Who executes actions?</td><td>Autonomous software systems</td></tr><tr><td>Who handles failures?</td><td>Autonomous systems first, humans upon escalation</td></tr></tbody></table>

### Characteristics

- Goal-oriented operational behavior
- Context-aware decision making
- Forecast-driven optimization
- Dynamic adaptation to changing conditions
- Human escalation rather than continuous supervision
- Continuous optimization across multiple objectives

### Key Requirements

Level 3 systems should include:

- Human override capability
- Policy enforcement mechanisms
- Audit logging
- Cybersecurity protections
- Fallback operational modes
- Confidence scoring and escalation logic
- Safety envelopes and operational constraints

### Relevant Standards

Existing standards partially address autonomous operation today. Relevant references include:

- IEEE 2030.7 and 2030.8
- IEC 62351 — Power system cybersecurity
- NIST Cybersecurity Framework
- Emerging AI governance and operational safety standards

Further industry standardization may be required to fully define autonomous microgrid operation.

---

# Operational Criticality

Not all microgrid capabilities carry the same operational importance or risk.

This framework distinguishes between different classes of operational criticality.

## Safety-Critical Capabilities

Capabilities whose failure or misuse could threaten human safety, equipment safety, or grid stability.

Examples:

- Protection relay operation
- Islanding and reconnection
- Overcurrent protection
- Emergency load shedding
- Battery thermal protection
- Voltage and frequency stabilization

These capabilities typically require strict operational constraints, auditability, and human override mechanisms.

## Business-Critical Capabilities

Capabilities necessary for the commercial and operational sustainability of the microgrid business.

Examples:

- Customer billing
- Payment processing
- Remote service disconnection
- Tariff enforcement
- Revenue collection
- Customer account management

These capabilities are operationally important but must remain subordinate to safety-critical protections.

## Optimization Capabilities

Capabilities intended to improve efficiency, economics, customer experience, or asset utilization.

Examples:

- Energy arbitrage optimization
- EV charging optimization
- Demand response coordination
- Forecast-driven battery dispatch
- Predictive maintenance
- Customer energy recommendations

Optimization capabilities should degrade gracefully without compromising safety or core operations.

## Supporting Capabilities

Capabilities that support operational continuity, efficiency, maintenance, coordination, or administrative workflows, but whose temporary failure does not immediately compromise safety or core service delivery.

Examples:

- Maintenance scheduling
- Reporting systems
- Asset inventory management
- Customer notifications
- Workforce coordination
- Historical analytics
- Non-critical integrations

Supporting capabilities improve operational effectiveness and resilience but are generally lower priority during constrained or degraded operations.

## Informational Capabilities

Capabilities whose primary purpose is visibility, insights, diagnostics, learning, or reporting without direct operational authority over the system.

Examples:

- Dashboards
- Historical reporting
- Data visualization
- Energy usage insights
- Community analytics
- Educational interfaces
- Public transparency portals

Informational capabilities provide situational awareness and decision support but typically do not directly influence operational behavior.

---

# Applying the Framework

The framework is intended to classify autonomy at the capability level rather than the whole microgrid level.

Example:

<table id="bkmrk-asset-foundational-c"><thead><tr><th>Asset</th><th>Foundational Capability Domain</th><th>Operational Function</th><th>Autonomy Level</th></tr></thead><tbody><tr><td>Smart Meter</td><td>Observability</td><td>Usage telemetry</td><td>Level 2</td></tr><tr><td>Battery Storage</td><td>Steering</td><td>Battery dispatch</td><td>Level 3</td></tr><tr><td>Diesel Generator</td><td>Steering</td><td>Generator operation</td><td>Level 1</td></tr><tr><td>EV Chargers</td><td>Observability</td><td>Charger monitoring</td><td>Level 2</td></tr><tr><td>EV Chargers</td><td>Steering</td><td>Charging orchestration</td><td>Level 3</td></tr><tr><td>Billing System</td><td>Commercial Operations</td><td>Automated billing</td><td>Level 2</td></tr><tr><td>Smart Relay</td><td>Steering</td><td>Service disconnection</td><td>Level 3</td></tr></tbody></table>

This allows gradual evolution toward autonomy without requiring the entire microgrid to transition simultaneously.

---

# Implications for a Microgrid OS

A Microgrid OS designed around this framework should:

- Treat foundational capabilities as modular services
- Support mixed autonomy levels simultaneously
- Allow policy-driven escalation to humans
- Maintain secure telemetry and control channels
- Provide auditability and operational transparency
- Support standards-based interoperability
- Maintain operational safety boundaries
- Support both edge and cloud orchestration architectures

The Microgrid OS becomes the orchestration layer coordinating assets, capabilities, policies, and autonomy levels across the energy system.

# Metering protocols: DLMS/COSEM, OBIS, Modbus, MQTT (and NFE CHINT register map)

> Traceable explainer: how metering data actually moves, where DLMS/COSEM, OBIS, Modbus, MQTT and HTTP each sit, and how NFE's live CHINT registers map to the OBIS standard vocabulary. Compiled 2026-08-10. Companion to "NFE metering strategy + Glen Street-EMS".

## The layer cake (mental model)

Networking is layers. Each solves one problem and talks only to the layer above and below.

| Layer | Job | Examples |
| --- | --- | --- |
| Link | move bits over one physical medium | RS485, Ethernet, WiFi |
| Network (IP) | address and route between any machines | IP |
| Transport (TCP) | reliable, ordered byte-stream between two programs | TCP, UDP |
| Application | what the two programs actually say | HTTP, MQTT, Modbus, DLMS |

Key point: **MQTT, HTTPS and DLMS/COSEM are all application-layer.** MQTT and HTTPS run on top of TCP (transport) on top of IP (network). MQTT is NOT a transport or network protocol.

> One clean way to hold it all: IP gets you to the right building. TCP is registered mail that guarantees the whole message. Modbus/DLMS is the local interview with one meter (DLMS adds a shared vocabulary and an ID badge). OBIS/COSEM/SunSpec is that shared vocabulary. MQTT is the courier network carrying notes across the village and orders back. HTTP is a different courier that only does "go fetch one thing and return".

- MQTT: application, over TCP, port 1883 (8883 with TLS)
- HTTPS: HTTP + TLS over TCP, port 443
- DLMS/COSEM: application; rides serial (HDLC) OR TCP/IP directly
- Modbus RTU (NFE's meter to Pi link): application, straight over RS485 serial, no IP at all (why it is the simplest thing on site)

## Three separate jobs, often confused

- **Vocabulary** (what a value means): OBIS / COSEM for meters, SunSpec for inverters.
- **Local interrogation** (talk to one device): Modbus or DLMS.
- **Messaging** (move data between many nodes, up and down): MQTT or HTTP.

You put COSEM-modelled data inside an MQTT message. They are not competitors: MQTT is the envelope, COSEM is the language on the page.

## MQTT vs HTTPS

- HTTPS is request/response, pull: client asks, server answers, one round trip. The server cannot easily push to a device.
- MQTT is publish/subscribe through a broker, push: a device holds one persistent TCP socket to a broker and publishes to a topic; subscribers get pushed the message instantly. Tiny 2-byte header, QoS levels, retained last value, last-will (detect a dead node), pushes both ways (telemetry up, commands down), survives flaky low-bandwidth links.
- The Street-EMS village dashboard uses MQTT: it pushes "TURN OFF SSR0" down to a specific cabinet on topic `openami/StreetPoleEMS_<id>/cmd` while readings stream up.

**MQTT over the internet?** Yes, it is just TCP. Devices make an outbound connection to a broker, so no inbound port-forwarding through the site modem, ideal for field gear on cellular.

**Why not DLMS/COSEM over HTTPS?** It buys nothing: DLMS already has its own TCP transport and its own message-level crypto (AES-128-GCM). And DLMS is a point-to-point session with one meter, not a fan-in/out telemetry bus. So the natural split is DLMS or Modbus to talk to the meter locally, MQTT to move the results around.

## DLMS/COSEM, unpacked

- **COSEM** (Companion Specification for Energy Metering) is the data model: every value is an object of an interface class (Register, Profile Generic for load profiles, Clock, Disconnect Control for the relay, etc.).
- **OBIS** (OBject Identification System) names each object with a six-group code A-B:C.D.E.F. Example: `1-0:1.8.0` = total active energy imported (what you bill).
- **DLMS** (Device Language Message Specification) is the protocol: GET an attribute, SET an attribute, ACTION a method, inside an authenticated, encrypted association.
- Standardised as IEC 62056. Certified by the DLMS User Association.

## The distinction: Modbus register vs COSEM "register"

A meter does NOT contain Modbus registers and COSEM registers side by side. They are two alternative languages for the same physical measurements. A given meter speaks one (or, on high-end dual-interface meters, both via separate ports).

- **Modbus register** = a numbered 16-bit memory slot at an address (e.g. `0x2004`). Dumb storage. It is meaningless without the vendor manual telling you "0x2004 is active power". The meaning lives in a PDF, not in the data.
- **COSEM Register (object)** = a self-describing object that carries its own unit and scaler, addressed by a global OBIS code that means the same thing on every compliant meter. (COSEM has an interface class literally named "Register", class_id 3 - hence the word collision. It is an object, not a memory slot.)

NFE's CHINT DDSU666 / DTSU666 are **Modbus-only** meters: inside them there are only Modbus registers, no COSEM, no OBIS. The OBIS column below is a translation NFE applies in software (in the logger / EMS / OpenAMI layer); the meter itself never knows about OBIS. The value of doing it: the meaning stops living in the CHINT manual and becomes the industry-standard, self-describing vocabulary.

## NFE CHINT register to OBIS map

Single-phase DDSU666 (tenant meters, one phase). Source: `nfe-modbus-energy-logger/src/meter_reader.py` and the OpenEMS `Meter.Chint.DDSU666` driver.

| Quantity | Modbus register (float) | OBIS code | Meaning |
| --- | --- | --- | --- |
| Voltage | 0x2000 | 1-0:32.7.0 | Instantaneous voltage L1 |
| Current | 0x2002 | 1-0:31.7.0 | Instantaneous current L1 |
| Active power | 0x2004 | 1-0:1.7.0 | Instantaneous active power (import +) |
| Power factor | 0x200A | 1-0:13.7.0 | Power factor |
| Frequency | 0x200E | 1-0:14.7.0 | Frequency |
| Import energy | 0x4000 | 1-0:1.8.0 | Total active energy imported (billing) |
| Export energy (invert cfg) | 0x4000 | 1-0:2.8.0 | Total active energy exported |

Three-phase DTSU666 (aggregate meter_100):

| Quantity | Modbus register(s) (float) | OBIS code(s) | Meaning |
| --- | --- | --- | --- |
| Voltage L1/L2/L3 | 0x2006 (x3) | 32.7.0 / 52.7.0 / 72.7.0 | Instantaneous phase voltages |
| Current L1/L2/L3 | 0x200C (x3) | 31.7.0 / 51.7.0 / 71.7.0 | Instantaneous phase currents |
| Active power total + L1/L2/L3 | 0x2012 (x4) | 1.7.0 / 21.7.0 / 41.7.0 / 61.7.0 | Instantaneous active power |
| Power factor | 0x202A | 13.7.0 | Power factor total |
| Frequency | 0x2044 | 14.7.0 | Frequency |
| Import energy | 0x4000 | 1-0:1.8.0 | Total active energy imported |

Note: the DDSU666 driver reads active power as already scaled kW; the DTSU666 needs per-manual scaling (Table 11: V/10, I x0.001, P x0.0001, PF x0.001, F x0.01). Minor code note: the logger's DTSU `REGISTERS` dict lists PF at 0x2020 but `read()` polls 0x202A; 0x202A is the one in use.

## Why two OpenEMS drivers (meter and inverter)

Two physical devices with different proprietary Modbus maps means two drivers:

- CHINT meter (`MeterChintDdsu666Impl`) reads 0x2000+; implements the `ElectricityMeter` Nature.
- SRNE inverter (`SrneEssImpl`) reads a totally different map at 0x0100 (SoC), 0x0101 (voltage), 0x0102 (current); implements the `SymmetricEss` / `HybridEss` Natures.

OpenEMS "Natures" (ElectricityMeter, SymmetricEss) are abstract interfaces both drivers map into, so the rest of OpenEMS sees a uniform API regardless of vendor. That is the local equivalent of what OBIS/COSEM and SunSpec do industry-wide.

The real prize of the standards is not one driver for meter plus inverter. It is one driver per device TYPE that works across every compliant vendor: any DLMS meter uses the same meter driver, any SunSpec inverter the same inverter driver. That removes the per-vendor Modbus-map work NFE did for both the CHINT and the SRNE. OpenEMS Natures give that uniformity on the edge (after the driver); DLMS and SunSpec give it at the wire (removing the driver work).

## OBIS vs profiles (IDIS / OpenAMI): naming is not interoperability

OBIS names things, it does not force a meter to implement or behave the same way. DLMS/COSEM is a large, flexible toolkit and leaves most choices to the manufacturer: which OBIS objects are actually present, which data types and scalers, which security suite, which communication profile, which optional events. So two meters can both be DLMS/COSEM compliant and both use OBIS and still not interoperate out of the box. Compliant is not the same as interoperable.

**IDIS** (Interoperable Device Interface Specifications) is an industry association profile that sits on top of DLMS/COSEM/OBIS and removes the optionality: it mandates exactly which OBIS objects must be present and how they behave, the data types, security and events, a fixed communication profile, and an interoperability certification (conformance plus multi-vendor testing). Packages by transport: Package 1 (basic, local/optical + core residential objects), Package 2 (power-line comms PRIME/G3 + data concentrators), Package 3 (cellular/IP). Any two IDIS-certified devices genuinely interchange.

Mental model: DLMS/COSEM is the grammar and a giant dictionary with optional dialects; OBIS gives every word one fixed meaning; IDIS is a mandated phrasebook plus accent everyone certifies to, so a whole conversation is portable, not just the words.

Why it matters here: even if two meters both spoke OBIS, if they exposed different object sets over different links you would still write per-vendor glue (the same thing that produced two OpenEMS drivers). A profile is what makes "buy any certified meter, one driver, plug and play" real. IDIS is the heavyweight, utility-grade version of exactly what OpenAMI aims to be for off-grid villages: a mandated, open, lightweight village-metering profile on top of the vocabulary. NFE does not need full IDIS, but it does need a profile, and that is OpenAMI's whole purpose.

## How OpenAMI sits on top

OpenAMI (IEEE Smart Village) is the actionable, utility-facing telemetry layer above a village feeder. It does not reinvent meter semantics: it composes OBIS/DLMS/COSEM (meters), SunSpec (inverters/DER), MQTT (transport), IEEE 2030.5 and 1547 (DER control). Its value-add is two-way, village-edge, policy-driven control and a billing cache, run cloudlessly and cheaply.

## Sources

Element room "Smart Village Energy Interest Group"; isv.wiki; `nfe-modbus-energy-logger/src/meter_reader.py`; OpenEMS drivers `io.openems.edge.meter.chint.ddsu666` and `io.openems.edge.ess.srne`; IEC 62056 (DLMS/COSEM); DLMS User Association Blue Book (OBIS).

# Inverter-monitor notifications: hardening + tuning (ADR-012)

> How the NFE inverter-monitor decides what to alert on, and the 2026-08-10 hardening pass that killed the nightly "Battery low" noise and closed several alert-integrity gaps. Source of truth is the code + ADR-012 in nfe-modbus-energy-logger; this is the team-facing summary.

## What triggered it

A "[NFE Nansana] Battery low - below 80 percent" email fired at 79% while the battery was doing normal peak-window arbitrage. 79% is not low; 80% was simply in the alert threshold set, which a normally-cycling battery crosses every evening. An end-to-end review found that plus several real gaps.

## What changed (all live on the VM)

- **Thresholds 80,50,30,20,10 -> 30,20,10.** 80/50 crossed nightly on normal arbitrage. Alerts now fire only at genuinely-low SoC. Override per site with `MONITOR_SOC_THRESHOLDS`.
- **Debounce is now actually wired.** A repeat/oscillating low-SoC crossing is suppressed within a cooldown (`MONITOR_SOC_DEBOUNCE_SECONDS`, default 6h). It existed and was tested but had never been connected.
- **Severity scales with the level.** A 30% crossing is a WARNING (amber); at or under 10% it is CRITICAL (red). Not every low-SoC is the same red alarm anymore.
- **Silent-outage closed.** A dead inverter/link while the Pi stays up used to be invisible (the heartbeat kept firing). New `data_stale` (critical) / `data_restored` alerts cover it, after N failed reads (`MONITOR_DATA_STALE_AFTER`, default 3), debounced. The old "Inverter offline" is renamed "Monitor offline" - it only ever meant the Pi/host/network is down.
- **No more false outages from one bad frame.** A grid/battery source change now needs N consecutive readings to confirm (`MONITOR_GRID_CONFIRM_CYCLES`, default 2). A single corrupt Modbus frame can no longer email a false grid-lost/restored pair.
- **Boot-into-low-SoC now alerts** (previously silent until it recovered and re-crossed). grid_restored shows the outage duration.
- **Delivery is retried.** A one-cycle notifier or SMTP blip no longer silently drops a grid_lost - both the POST and the SMTP send retry.
- **Security.** The notifier refuses to bind a non-loopback interface with an empty token, so the /alert endpoint (which emails the whole team) can never be exposed unauthenticated.

## The alert ladder (unchanged rungs)

- CRITICAL (red): monitor offline, data stale, SoC at/under 10%, battery empty, fault.
- WARNING (amber): grid lost (on battery), SoC below a threshold above the floor, over-temp.
- RESOLVED (green): grid restored, back online, data restored.
- INFO (blue): daily energy/arbitrage summary. Charge/discharge start-stop do not email individually.

## Deploy + rollback

Built from merged main and deployed to the NFE OpenEMS VM as `nfe-monitor:local` + `nfe-notifier:local` (local build; the GHCR pipeline path unlocks once the nfe-monitor package is public). Previous images tagged `:prev` for rollback (`docker tag nfe-monitor:prev nfe-monitor:local && docker compose up -d`). Verified live: both containers stable (0 restarts), notifier listening + auth enforced (bad token -> 401), monitor heart-beating.

## Traceable in repo

ADR-012-notification-hardening, docs/inverter-monitor.dsl (C4 model), docs/notification-severity-standard.md, PR #69. 255 tests, 99% coverage.

# SRNE TOU arbitrage: plan (#67)

> The plan to turn on time-of-use battery arbitrage on the Sezibwa/Nansana SRNE inverter (logger issue #67): charge the battery from the grid off-peak, discharge it to the load at peak, using the SRNE charge/discharge SCHEDULE registers written through the guarded write path we proved with #53. Compiled 2026-08-11.

## The gap (why we are leaving money on the table)

The inverter already CHARGES off-peak (charge window is set to 00:00-06:00) but it does NOT discharge at peak - the discharge time-windows are all 0 (off). Live-confirmed 2026-08-10: at peak the battery sat idle on grid at ~79% while ~1.3 kW of load was served straight from the grid. So we pay the peak grid rate for load we could have covered with cheap off-peak energy already sitting in the battery. Turning on the discharge window closes that.

## The economics (Code 10.2, what NFE pays the utility)

| Period | Window | Rate (UGX/kWh) |
| --- | --- | --- |
| Off-peak | 00:00-06:00 | 343.20 |
| Shoulder | 06:00-18:00 | 577.11 |
| Peak | 18:00-24:00 | 666.50 (Q3 2026) |

Arbitrage = buy at 343 off-peak, avoid ~666 at peak = ~320 UGX/kWh gross, minus battery wear. Usable battery ~10.49 kWh; discharging ~5-7 kWh at peak while holding a reserve gives a gross saving in the low thousands of UGX per day. The daily energy/cash summary (#26, already live) already computes charged kWh + buy cost, discharged kWh + value, wear, and net margin - so once this is on we MEASURE the real number, not guess.

## The levers (SRNE registers, decoded firmware v925, RW)

Written through the same guarded path as #53 (SafeWriteHandler: default-off, verified-machine-state gate, one-shot FC16, readback-verified). Time encoding = hour*256 + minute (e.g. 18:00 = 4608, 06:00 = 1536).

| Function | Register(s) | Live (2026-08-09) | Target |
| --- | --- | --- | --- |
| Charge window 1 | 0xE026 / 0xE027 | 00:00-06:00 | keep (off-peak) |
| Charge windows 2/3 | 0xE028/E029, 0xE02A/E02B | unset | optional |
| Discharge windows 1/2/3 | 0xE02D-0xE032 | ALL 0 (off) | window 1 = 18:00-24:00 (peak) |
| Output priority | 0xE204 | 3 | confirm = battery-first in-window |
| Charge priority | 0xE20F | tbd | grid, off-peak |
| Switch-to-line SoC (reserve floor) | 0xE01F | 10 | raise to protect reserve |
| Switch-to-battery SoC | 0xE020 | 90 | tune |
| Discharge cutoff SoC | 0xE00F | 5 | hard floor |
| Inverter RTC | set 0xE034-0xE036 / read 0x020C-0x020E | must be correct | verify, set if drifted |

NOT available on this firmware (confirmed Illegal-data-address): real-time active-power dispatch (0xE047-0xE04D, 0xE400-0xE402). We do NOT need it - scheduling covers TOU arbitrage.

## Safety framing: reserve vs savings (the core tension)

The site's PRIMARY mission is backup during grid outages. Discharging at peak spends reserve exactly in the evening window when outages are most likely. So arbitrage must never drain below a backup reserve. Policy: hold >= 50% reserve until 30 days of outage data are collected (per CUSTOM_CODE/CLAUDE.md), then revisit. The discharge must STOP at the reserve floor, not run down to the discharge-cutoff. Phase 1 confirms exactly which register enforces that floor on this firmware (the switch-to-line SoC band vs a per-window reserve). RTC accuracy is critical - a wrong clock means the windows fire at the wrong time.

## The build (mirrors #53, which is proven)

**Phase 1 - Prove the schedule-write path (DAYTIME, no customer disruption):**
- Fresh bus-quiet mbpoll read of every schedule/RTC/reserve register above = current ground truth (stop edge + mbpoll, 5s settle, read, restart - the method from #53).
- Extend the SRNE OpenEMS component to expose the schedule + RTC + reserve registers as guarded-writable settings, reusing the SafeWriteHandler infra from #53.
- Safe live test: write an UNUSED, far-from-now discharge window (e.g. a mid-morning slot), verify the readback, restore it to 0. Verify RTC reads wall-clock; set if off. This proves writes land and read back without ever activating a real discharge in front of customers.
- Tests to the 90% coverage gate; ADR; PR; git -> deploy.

**Phase 2 - Program the arbitrage schedule (DAYTIME, supervised):**
- Through the guarded write config (gateway config -> deploy, no box edits): set discharge window 1 = 18:00-24:00, confirm charge window 1 = 00:00-06:00, set the reserve floor to protect 50%, confirm output/charge priority.
- Watch one full cycle live: does it discharge at peak (battery carries the load, grid draw drops)? does it stop at the reserve floor? does it recharge off-peak overnight?

**Phase 3 - Measure + tune:**
- The daily #26 summary reports the actual arbitrage margin each morning. Tune the window edges and reserve against real margin + the outage log (the 30-day rule before dropping reserve below 50%).

## Guardrails (all carried from tonight's #53 discipline)

Live-test before commission. Daytime writes only. Guarded write path (default-off, verified-state gate, one-shot, readback-verified). git -> deploy, never hand-edit the box. Bus-quiet reads (stop edge + mbpoll + 5s). Reserve-first: backup mission beats savings.

## Open questions Phase 1 must answer

1. Which register actually enforces the reserve floor on v925 (switch-to-line SoC vs a per-window reserve field)?
2. Is the inverter RTC accurate right now? (windows fail silently if not)
3. Output-priority (0xE204=3) semantics on this firmware - does it put battery first inside a discharge window while grid is present?