GithubHelp home page GithubHelp logo

smlpy's Introduction

SMLPY - monitor your power meter

What is it?

smlpy enables reading of smart meter language (sml) data from a smart power meter ("Stromzähler"). This library is intended for newer smart meters which support publishing data through an IR sender. Older power meters are not supported.

You need a working IR-reading device for this, e.g. https://shop.weidmann-elektronik.de/index.php?page=product&info=24 which must be connected to a USB port.

Please note that this library only supports a small part of the SML-spec, especially the sending part is intentionally omitted

How to use it?

pip install smlpy

From the shell: go to the folder containing smlpy and modify data_reader.dump to account for your baudrate etc.

This should dump the readings to the shell:

python data_reader.py 

programmatic usage:

This dumps the results to the console:

from smlpy import data_reader
import asyncio
loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(data_reader.dump_results()) # todo set baud rate etc!
finally:
    # see: https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.shutdown_asyncgens
    loop.run_until_complete(loop.shutdown_asyncgens())
    loop.close()

If you need programmatic access to the data, use

from smlpy import data_reader
import asyncio
import serial
loop = asyncio.get_event_loop()
try:
    default_port_settings = data_reader.PortSettings(port='/dev/ttyUSB0',
                                         baudrate=9600,
                                         bytesize=serial.EIGHTBITS,
                                         parity=serial.PARITY_NONE,
                                         stopbits=serial.STOPBITS_ONE,
                                         wait_time=data_reader.WAIT_TIME)
    async for result in data_reader.main(default_port_settings):
        print(result.dump_to_json())
        # e.g. save to DB
finally:
    # see: https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.shutdown_asyncgens
    loop.run_until_complete(loop.shutdown_asyncgens())
    loop.close()

Tests

  1. clone this project
  2. install pytest
  3. pytest test
  4. Optional:
    1. Please clone libsml-testing into a folder next to the smlpy folder
    2. Remove the @pytest.mark.skip("manual only")flag and run also the test against other power meter data. A lot of the data is broken though

If you have additional data please add a test case and submit a PR

Device compatibility

I have test this library with data from these devices:

  • EMH EHZ-K (eHZ Generation K)
  • EMH EHZ-361L5R
  • EMH EHZ-HW8E2A5LOEK2P
  • EMH EHZ-GW8E2A500AK2
  • ITRON Openway 3
  • ISKRA MT175 EHZ
  • ISKRA MT691 EHZ

Does not work:

  • HOLLEY DTZ541 ZDBA

smlpy's People

Contributors

christiansauer avatar

Watchers

 avatar

smlpy's Issues

async Error when using sample

Thanks!
In fact Data Reader works fine.
But when I try to launch one of the functions like in your sample to programmatically access the JSON then an error ia raised:

async for result in data_reader.main(default_port_settings):
^
SyntaxError: 'async for' outside async function

Error when installing pip3 install smlpy

user@iobroker:~/smlpy$ python3 -m venv venv
user@iobroker:~/smlpy$ source venv/bin/activate
(venv) user@iobroker:~/smlpy$ pip3 install smlpy
Collecting smlpy
  Using cached smlpy-0.2.3-py3-none-any.whl (9.3 kB)
Collecting jsons<2.0.0,>=1.3.0
  Using cached jsons-1.6.3-py3-none-any.whl (60 kB)
Collecting loguru<0.6.0,>=0.5.3
  Using cached loguru-0.5.3-py3-none-any.whl (57 kB)
Collecting pyserial<4.0,>=3.5
  Using cached pyserial-3.5-py2.py3-none-any.whl (90 kB)
Collecting pyserial-asyncio<0.6,>=0.5
  Using cached pyserial_asyncio-0.5-py3-none-any.whl (7.5 kB)
Collecting pyyaml<6.0.0,>=5.3.1
  Using cached PyYAML-5.4.1.tar.gz (175 kB)
  Installing build dependencies ... done
  Getting requirements to build wheel ... error
  error: subprocess-exited-with-error
  
  × Getting requirements to build wheel did not run successfully.
  │ exit code: 1
  ╰─> [54 lines of output]
      running egg_info
      writing lib3/PyYAML.egg-info/PKG-INFO
      writing dependency_links to lib3/PyYAML.egg-info/dependency_links.txt
      writing top-level names to lib3/PyYAML.egg-info/top_level.txt
      Traceback (most recent call last):
        File "/home/user/smlpy/venv/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 353, in <module>
          main()
        File "/home/user/smlpy/venv/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 335, in main
          json_out['return_val'] = hook(**hook_input['kwargs'])
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/user/smlpy/venv/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 118, in get_requires_for_build_wheel
          return hook(config_settings)
                 ^^^^^^^^^^^^^^^^^^^^^
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/build_meta.py", line 325, in get_requires_for_build_wheel
          return self._get_build_requires(config_settings, requirements=['wheel'])
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/build_meta.py", line 295, in _get_build_requires
          self.run_setup()
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/build_meta.py", line 311, in run_setup
          exec(code, locals())
        File "<string>", line 271, in <module>
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/__init__.py", line 103, in setup
          return distutils.core.setup(**attrs)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/_distutils/core.py", line 184, in setup
          return run_commands(dist)
                 ^^^^^^^^^^^^^^^^^^
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/_distutils/core.py", line 200, in run_commands
          dist.run_commands()
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/_distutils/dist.py", line 969, in run_commands
          self.run_command(cmd)
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/dist.py", line 968, in run_command
          super().run_command(command)
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/_distutils/dist.py", line 988, in run_command
          cmd_obj.run()
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/command/egg_info.py", line 321, in run
          self.find_sources()
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/command/egg_info.py", line 329, in find_sources
          mm.run()
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/command/egg_info.py", line 550, in run
          self.add_defaults()
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/command/egg_info.py", line 588, in add_defaults
          sdist.add_defaults(self)
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/command/sdist.py", line 102, in add_defaults
          super().add_defaults()
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/_distutils/command/sdist.py", line 250, in add_defaults
          self._add_defaults_ext()
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/_distutils/command/sdist.py", line 335, in _add_defaults_ext
          self.filelist.extend(build_ext.get_source_files())
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "<string>", line 201, in get_source_files
        File "/tmp/pip-build-env-gl5ks36t/overlay/lib/python3.11/site-packages/setuptools/_distutils/cmd.py", line 107, in __getattr__
          raise AttributeError(attr)
      AttributeError: cython_sources
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error

× Getting requirements to build wheel did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.

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.