Code Monkey home page Code Monkey logo

sma-emeter-simulator's Introduction

sma-emeter-simulator

An SMA(TM) emeter simulator written in C++. It mimics an SMA(TM) emeter device on your local network by generating the same kind of udp packets that an actual SMA(TM) emeter would generate.

SMA-Emeters(TM) send out udp packets including electrical power and energy measurements at intervals of 1000ms. The general udp packet format is specified in a publicly available specification document provided by the manufacturer (https://developer.sma.de/fileadmin/content/global/Partner/Documents/SMA_Labs/EMETER-Protokoll-TI-en-10.pdf).

The simulator supports different emeter types. Depending on how you configure the simulator, it can generate different udp packet formats:

Emeter-10

Susy-ID: 270 (0x010E)
Protocol-ID: 0x6069
UDP packet size: 600 bytes
SMA header size: 18 bytes
Multicast: 239.12.255.254 port 9522

Emeter-20

Susy-ID: 349 (0x015D)
Protocol-ID: 0x6069
UDP packet size: 608 bytes since frequency was added with firmware version 2.03.4.R; 600 bytes was used before
SMA header size: 18 bytes
Multicast: 239.12.255.254 port 9522

Sunny Home Manager 20

Susy-ID: 372 (0x0174)
Protocol-ID: 0x6069
UDP packet size: 608 bytes since frequency was added with firmware version 2.03.4.R; 600 bytes was used before
SMA header size: 18 bytes
Multicast: 239.12.255.254 port 9522
Unicast: if configured

Firmware version 2.07.x used a different format for unicast transmission:
Susy-ID: 372 (0x0174)
Protocol-ID: 0x6081
UDP packet size: 610 bytes
SMA header size: 20 bytes
Unicast: if configured

The executable starts by assembling a udp datagram according to one of the above mentioned configurations.

Afterwards it starts an infinite main loop. Within the main loop it repetitively transmits the same udp datagram every 1000 milliseconds, while updating the timestamp inside the packet.

The software comes as is. No warrantees whatsoever are given and no responsibility is assumed in case of failure. There is neither a GUI nor a configuration file. Configurations must be tweaked by modifying main.cpp.

The code is based on a Speedwire(TM) access library implementation https://github.com/RalfOGit/libspeedwire. The libspeedwire library implements a full parser for the sma header and the emeter datagram structure, including obis filtering. In addition, it implements some parsing functionality for inverter query and response datagrams. For convenience you may want to place the libspeedwire/ folder right next to the src/ and include/ folders of this repository.

The accompanied CMakeLists.txt assumes the following folder structure:

sma-emeter-simulator
    src
    include
    libspeedwire
        src
        include
        CMakeLists.txt
    ... build path ...
    CMakeLists.txt

The code has been tested against the following environment:

OS: CentOS 8(TM), IDE: VSCode (TM)
OS: Windows 10(TM), IDE: Visual Studio Community Edition 2019 (TM)

Measurements are encoded as OBIS data fields. OBIS is defined in IEC 62056-6-1. There is a German wikipedia page https://de.wikipedia.org/wiki/OBIS-Kennzahlen about it. The order of measurements in SMA(TM) emeter packets is as described below. The values provided are just examples:

// totals
ObisData::PositiveActivePowerTotal   (0,  1, 4,  121.60) 
ObisData::PositiveActiveEnergyTotal  (0,  1, 8, 1320.34) 
ObisData::NegativeActivePowerTotal   (0,  2, 4,    0.00)
ObisData::NegativeActiveEnergyTotal  (0,  2, 8,  305.03) 
ObisData::PositiveReactivePowerTotal (0,  3, 4,    0.00) 
ObisData::PositiveReactiveEnergyTotal(0,  3, 8,    5.90) 
ObisData::NegativeReactivePowerTotal (0,  4, 4,  188.90) 
ObisData::NegativeReactiveEnergyTotal(0,  4, 8,  949.68)
ObisData::PositiveApparentPowerTotal (0,  9, 4,  224.60)
ObisData::PositiveApparentEnergyTotal(0,  9, 8, 1757.41) 
ObisData::NegativeApparentPowerTotal (0, 10, 4,    0.00) 
ObisData::NegativeApparentEnergyTotal(0, 10, 8,  327.62) 
ObisData::PowerFactorTotal           (0, 13, 4,    0.54) 
ObisData::Frequency                  (0, 14, 4,   50.16) // since firmware version 2.03.4.R

// L1
ObisData::PositiveActivePowerL1      (0, 21, 4,    0.00) 
ObisData::PositiveActiveEnergyL1     (0, 21, 8,  337.53) 
ObisData::NegativeActivePowerL1      (0, 22, 4,   21.70) 
ObisData::NegativeActiveEnergyL1     (0, 22, 8,  141.54) 
ObisData::PositiveReactivePowerL1    (0, 23, 4,    0.00) 
ObisData::PositiveReactiveEnergyL1   (0, 23, 8,    2.48)
ObisData::NegativeReactivePowerL1    (0, 24, 4,   22.30) 
ObisData::NegativeReactiveEnergyL1   (0, 24, 8,  176.48) 
ObisData::PositiveApparentPowerL1    (0, 29, 4,    0.00) 
ObisData::PositiveApparentEnergyL1   (0, 29, 8,  473.68) 
ObisData::NegativeApparentPowerL1    (0, 30, 4,   31.10) 
ObisData::NegativeApparentEnergyL1   (0, 30, 8,  144.26) 
ObisData::CurrentL1                  (0, 31, 4,    0.18) 
ObisData::VoltageL1                  (0, 32, 4,  231.97) 
ObisData::PowerFactorL1              (0, 33, 4,    0.70) 
												 
// L2                                            
ObisData::PositiveActivePowerL2      (0, 41, 4,  160.80) 
ObisData::PositiveActiveEnergyL2     (0, 41, 8,  775.23) 
ObisData::NegativeActivePowerL2      (0, 42, 4,    0.00) 
ObisData::NegativeActiveEnergyL2     (0, 42, 8,   77.80) 
ObisData::PositiveReactivePowerL2    (0, 43, 4,    0.00) 
ObisData::PositiveReactiveEnergyL2   (0, 43, 8,    7.38) 
ObisData::NegativeReactivePowerL2    (0, 44, 4,  126.00) 
ObisData::NegativeReactiveEnergyL2   (0, 44, 8,  535.19) 
ObisData::PositiveApparentPowerL2    (0, 49, 4,  204.30) 
ObisData::PositiveApparentEnergyL2   (0, 49, 8,  974.19) 
ObisData::NegativeApparentPowerL2    (0, 50, 4,    0.00) 
ObisData::NegativeApparentEnergyL2   (0, 50, 8,   89.10) 
ObisData::CurrentL2                  (0, 51, 4,    1.12) 
ObisData::VoltageL2                  (0, 52, 4,  230.66) 
ObisData::PowerFactorL2              (0, 53, 4,    0.79) 
												 
// L3                                            
ObisData::PositiveActivePowerL3      (0, 61, 4,    0.00) 
ObisData::PositiveActiveEnergyL3     (0, 61, 8,  271.21) 
ObisData::NegativeActivePowerL3      (0, 62, 4,   17.60) 
ObisData::NegativeActiveEnergyL3     (0, 62, 8,  149.31) 
ObisData::PositiveReactivePowerL3    (0, 63, 4,    0.00) 
ObisData::PositiveReactiveEnergyL3   (0, 63, 8,    1.70) 
ObisData::NegativeReactivePowerL3    (0, 64, 4,   40.66) 
ObisData::NegativeReactiveEnergyL3   (0, 64, 8,  243.67)  
ObisData::PositiveApparentPowerL3    (0, 69, 4,    0.00) 
ObisData::PositiveApparentEnergyL3   (0, 69, 8,  434.62) 
ObisData::NegativeApparentPowerL3    (0, 70, 4,   44.30) 
ObisData::NegativeApparentEnergyL3   (0, 70, 8,  156.83) 
ObisData::CurrentL3                  (0, 71, 4,    0.23) 
ObisData::VoltageL3                  (0, 72, 4,  230.09) 
ObisData::PowerFactorL3              (0, 73, 4,    0.40) 

// software version, end of data
ObisData::SoftwareVersion            (144,0, 0, "2.03.4.R") 
ObisData::EndOfData                  (0,  0, 0, 0) 

sma-emeter-simulator's People

Contributors

ralfogit avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

sma-emeter-simulator's Issues

Not detected by Sunny Portal/Sunny Home Manager 2.0

Hi!

Thanks for sharing this project!

I tried adapting the code to get data from an unsupported solar panel inverter into Sunny Portal, but the portal doesn't detect this virtual e-meter. Would you happen to know what's required to make Sunny Portal detect it? The main device in my network is a Sunny Home Manager 2.0.

Thanks again!

Emeter UDP packet size

Hi @RalfOGit,

I'm just starting to develop a meter that sends out the information using the SMA protocol, so your library comes really useful. Thank you for your work!

Anyway, I have a real EMETER at hand and I see that the sent packets are 608 bytes in size. But when looking at your code here, I see you are using a payload size of 600 bytes instead. Is that correct?

uint8_t udp_packet[600];

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.