{"id":50803397,"url":"https://github.com/databus23/go-sml","last_synced_at":"2026-06-12T22:33:34.598Z","repository":{"id":350560684,"uuid":"1207378429","full_name":"databus23/go-sml","owner":"databus23","description":" pure-Go library for decoding Smart Message Language (SML) data","archived":false,"fork":false,"pushed_at":"2026-04-10T22:16:43.000Z","size":93,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-06T14:00:04.978Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/databus23.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-10T21:56:17.000Z","updated_at":"2026-04-10T22:16:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/databus23/go-sml","commit_stats":null,"previous_names":["databus23/go-sml"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/databus23/go-sml","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/databus23%2Fgo-sml","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/databus23%2Fgo-sml/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/databus23%2Fgo-sml/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/databus23%2Fgo-sml/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/databus23","download_url":"https://codeload.github.com/databus23/go-sml/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/databus23%2Fgo-sml/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34265491,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-12T22:33:32.546Z","updated_at":"2026-06-12T22:33:34.577Z","avatar_url":"https://github.com/databus23.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# go-sml\n\nA pure-Go library for decoding [Smart Message Language (SML)](https://de.wikipedia.org/wiki/Smart_Message_Language) data from German smart electricity meters. Zero external dependencies.\n\n```go\ngo get github.com/databus23/go-sml\n```\n\n## Quick Start\n\n### CLI tool\n\nA small command-line tool is included that prints readings in the same format\nas the C `sml_server`:\n\n```bash\ngo install github.com/databus23/go-sml/cmd/smlreader@latest\nsmlreader capture.bin\n# or from stdin:\nsmlreader -\n```\n\nOutput:\n\n```\n1-0:1.8.0*255#8391648.8#Wh\n1-0:15.7.0*255#163.5#W\n```\n\n### As a library\n\nDecode a raw SML payload and print all meter readings:\n\n```go\nfile, err := sml.Decode(payload)\nif err != nil {\n    log.Fatal(err)\n}\nfor _, entry := range file.Readings() {\n    if v, ok := entry.ScaledValue(); ok {\n        fmt.Printf(\"%s = %f %s\\n\", entry.OBISString(), v, entry.UnitString())\n    }\n}\n// Output:\n// 1-0:1.8.0*255 = 8391648.800000 Wh\n// 1-0:16.7.0*255 = 163.500000 W\n```\n\n## Streaming from a Serial Port\n\nFor continuous reading from a serial device (or any `io.Reader`), use `Listen`.\nIt handles transport framing, escape sequences, and CRC validation automatically:\n\n```go\nport, _ := os.Open(\"/dev/ttyUSB0\")\ndefer port.Close()\n\nerr := sml.Listen(ctx, port, func(file *sml.File) error {\n    for _, entry := range file.Readings() {\n        if v, ok := entry.ScaledValue(); ok {\n            fmt.Printf(\"%s = %.1f %s\\n\", entry.OBISString(), v, entry.UnitString())\n        }\n    }\n    return nil\n})\n```\n\nUse `ListenMessages` instead if you want per-message callbacks rather than\nper-file.\n\n## API Overview\n\n### Root package `sml`\n\n| Symbol | Description |\n|--------|-------------|\n| `Decode(data) (*File, error)` | Decode a complete SML payload (strict mode) |\n| `DecodeWithOptions(data, opts)` | Decode with configurable strictness |\n| `Listen(ctx, r, handler)` | Stream-decode from an `io.Reader` |\n| `ListenMessages(ctx, r, handler)` | Like `Listen`, but calls handler per message |\n| `File.Readings()` | Collect all `ListEntry` values from `GetListResponse` messages |\n| `ListEntry.ScaledValue()` | Apply scaler, return `float64` |\n| `ListEntry.OBISString()` | Format OBIS code as `\"A-B:C.D.E*F\"` |\n| `ListEntry.UnitString()` | DLMS unit name (e.g. `\"Wh\"`, `\"W\"`, `\"V\"`) |\n| `UnitName(code)` | Look up DLMS unit code directly |\n\n### Sub-package `transport`\n\n| Symbol | Description |\n|--------|-------------|\n| `NewReader(r) *Reader` | Wrap an `io.Reader` to extract SML transport frames |\n| `Reader.Next() ([]byte, error)` | Return next validated frame payload |\n\nThe transport layer auto-detects CRC-16/X.25 (standard) and CRC-16/Kermit\n(Holley DTZ541 meters).\n\n### Value Types\n\nSML values preserve their wire encoding width. Use a type switch on the\n`Value` interface:\n\n```go\nswitch v := entry.Value.(type) {\ncase sml.Uint32:\n    fmt.Println(\"unsigned 32-bit:\", uint32(v))\ncase sml.Int16:\n    fmt.Println(\"signed 16-bit:\", int16(v))\ncase sml.OctetString:\n    fmt.Printf(\"bytes: %x\\n\", []byte(v))\n}\n```\n\nAvailable types: `OctetString`, `Bool`, `Int8`, `Int16`, `Int32`, `Int64`,\n`Uint8`, `Uint16`, `Uint32`, `Uint64`.\n\n### Message Body Types\n\n`Message.Body` implements `MessageBody` and is one of:\n\n- `*OpenResponse`\n- `*CloseResponse`\n- `*GetListResponse` (contains meter readings)\n- `*AttentionResponse`\n- `*GetProcParameterResponse`\n- `*GetProfileListResponse`\n- `*GetProfilePackResponse`\n\n## Testing\n\n### Run all tests\n\n```bash\ngo test ./...\n```\n\n### Integration tests only\n\nThe integration tests decode 37 real meter captures and compare the output\nagainst golden files generated by the C reference implementation\n([libsml](https://github.com/volkszaehler/libsml)):\n\n```bash\ngo test -run TestGoldenFiles -v\n```\n\nTest data comes from [devZer0/libsml-testing](https://github.com/devZer0/libsml-testing)\nand covers 15+ meter models from manufacturers including EMH, DZG, Holley,\nISKRA, EasyMeter, eBZ, ITRON, and DrNeuhaus.\n\n### Fuzz tests\n\n```bash\ngo test -fuzz FuzzDecode -fuzztime 30s\ngo test -fuzz FuzzTransportReader -fuzztime 30s\n```\n\n## Regenerating Golden Files\n\nThe golden files in `testdata/golden/` are generated by piping each binary\ncapture through the C `sml_server` example program from\n[volkszaehler/libsml](https://github.com/volkszaehler/libsml).\n\n### Build sml_server from source\n\n```bash\ngit clone https://github.com/volkszaehler/libsml /tmp/libsml\ncd /tmp/libsml\nmake\n\n# On macOS the shared library target may fail — only the static library\n# is needed. Link sml_server manually:\ncc -o sml_server examples/sml_server.c -Isml/include sml/lib/libsml.a -lm\n```\n\n### Generate golden files\n\n```bash\nfor f in testdata/*.bin; do\n  name=$(basename \"$f\" .bin)\n  /tmp/libsml/sml_server - \u003c \"$f\" \u003e \"testdata/golden/${name}.txt\" 2\u003e\u00261\ndone\n```\n\nThe golden file format is one line per `GetListResponse` list entry:\n\n```\nOBIS#value#unit\n```\n\nwhere OBIS is `A-B:C.D.E*F`, value is the scaled numeric reading (or hex-formatted octet string), and unit is the DLMS unit name.\n\n### Using Docker (no local C toolchain)\n\n```bash\ndocker run --rm -v \"$(pwd)\":/work -w /work gcc:latest bash -c '\n  apt-get update -qq \u0026\u0026 apt-get install -y -qq uuid-dev \u003e /dev/null 2\u003e\u00261\n  git clone --quiet https://github.com/volkszaehler/libsml /tmp/libsml\n  cd /tmp/libsml \u0026\u0026 make \u003e /dev/null 2\u003e\u00261\n  for f in /work/testdata/*.bin; do\n    name=$(basename \"$f\" .bin)\n    ./examples/sml_server - \u003c \"$f\" \u003e \"/work/testdata/golden/${name}.txt\" 2\u003e\u00261\n  done\n'\n```\n\n## License\n\nApache License 2.0 — see [LICENSE](LICENSE).\n\n## Acknowledgements\n\n- [volkszaehler/libsml](https://github.com/volkszaehler/libsml) — C reference implementation\n- [devZer0/libsml-testing](https://github.com/devZer0/libsml-testing) — Real meter captures used for integration testing\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatabus23%2Fgo-sml","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdatabus23%2Fgo-sml","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatabus23%2Fgo-sml/lists"}