{"id":17216214,"url":"https://github.com/jobe3774/mbpv","last_synced_at":"2025-04-13T22:32:33.856Z","repository":{"id":237630579,"uuid":"215130462","full_name":"jobe3774/mbpv","owner":"jobe3774","description":"A raspend based application for reading out current values of my PV units inverters via Modbus-TCP and serve them via HTTP as JSON.","archived":false,"fork":false,"pushed_at":"2025-02-27T09:01:02.000Z","size":64,"stargazers_count":10,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-27T13:04:51.335Z","etag":null,"topics":["inverter","modbus","modbus-tcp","photovoltaic","pv-unit","pvoutput","python","python-3","python3","raspberry-pi","raspberry-pi-3","raspberrypi","raspend","sma","solar","solar-inverter","solar-power","sunny-boy"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jobe3774.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}},"created_at":"2019-10-14T19:39:00.000Z","updated_at":"2025-02-27T09:01:06.000Z","dependencies_parsed_at":null,"dependency_job_id":"70ca10cd-0e89-48e7-972f-ae1332964e1d","html_url":"https://github.com/jobe3774/mbpv","commit_stats":null,"previous_names":["jobe3774/mbpv"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jobe3774%2Fmbpv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jobe3774%2Fmbpv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jobe3774%2Fmbpv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jobe3774%2Fmbpv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jobe3774","download_url":"https://codeload.github.com/jobe3774/mbpv/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248790742,"owners_count":21162082,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["inverter","modbus","modbus-tcp","photovoltaic","pv-unit","pvoutput","python","python-3","python3","raspberry-pi","raspberry-pi-3","raspberrypi","raspend","sma","solar","solar-inverter","solar-power","sunny-boy"],"created_at":"2024-10-15T03:27:11.683Z","updated_at":"2025-04-13T22:32:33.579Z","avatar_url":"https://github.com/jobe3774.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mbpv - modbus photovoltaic (unit reader)\nA  [raspend](https://github.com/jobe3774/raspend) based application for reading out current values of my PV units inverters via Modbus-TCP. These values are exposed as a JSON string via HTTP, so that they can be displayed in a user interface like shown below.\n\nFor Modbus communication it uses [pyModbusTCP](https://github.com/sourceperl/pyModbusTCP).\n\nThe calculation of sunrise and sunset is based on SunMoon.py by Michael Dalder, which in turn is a port of Arnold Barmettler's JavaScript. See [here](https://lexikon.astronomie.info/java/sunmoon/) for more information.\n\nMy PV system uses two inverters of *SMA Solar Technology AG*. These are the models Sunny Boy 3.0 and 3.6 (SB3.0-1AV-40 (9319) / SB3.6-1AV-40 (9320)). Therefore **mbpv** is tailored to these inverters, but should be easily adaptable to other inverters that support Modbus-TCP. Check *SMA_Inverters.py* for the Modbus registers I used. Modify them or replace *SMA_Inverters.py* by your own implementation.\n\n## Configuration\n\n**mbpv** uses a JSON configuration file. The current configuration has the two mandatory nodes *Unit* and *Inverters*. The latter is just an array holding the node names for each inverter belonging to the current PV system. See *mbpv_config.json* for an example configuration.\n\n### Unit\n``` json\n  \"Unit\": {\n    \"startUp\": \"2019-02-27\", \n    \"location\": {\n      \"longitude\": 6.0838868,\n      \"latitude\": 50.7753455\n    },\n    \"expectedYieldKWHperKWP\": 925,\n    \"peakOutputInWP\": 6270\n  }\n```\nKey|Value\n---|-----\nstartUp | the day of the first start of the PV system\nlocation | the geocoordinates of the system (needed for sun time calculation)\nexpectedYieldKWHperKWP | the expected number of kWh per kWP for the location\npeakOutputInWP | the maximum power the system is able to generate\n\n### Inverters\nAs already mentioned, the node *Inverters* is only an array with the names of the nodes defining the inverters of the PV system. In the example below, we would have nodes named *sunnyboy1* to *sunnyboy3*. \n\n``` json\n  \"Inverters\": [\n    \"sunnyboy1\",\n    \"sunnyboy2\",\n    \"sunnyboy3\"\n  ],\n```\nEach inverter's node has the following structure:\n\n``` json\n  \"sunnyboy1\": {\n    \"totalYieldLastYear\": 0,\n    \"inverter\": {\n      \"name\": \"SUNNY BOY 3.0\",\n      \"host\": \"sunny-boy-30\",\n      \"port\": 502,\n      \"unitId\": 1,\n      \"maxOutput\": 3000\n    },\n    \"maxPeakOutputDay\": 0,\n    \"totalYieldCurrYear\": 0,\n    \"dayYield\": 0,\n    \"totalYield\": 0,\n    \"currentOutput\": 0,\n    \"internalTemperature\": 0.0,\n    \"currentState\": \"ok\",\n    \"maxPeakTime\" : \"HH:MM\"\n  },\n  ...\n  \"sunnyboy2\": {\n  },\n  ...\n```\nKey | Value \n----|-------\ntotalYieldLastYear|holds the total yield until change of the year\ntotalYieldCurrYear|holds the total yield since change of the year\ndayYield|the yield of the current day\ntotalYield|sum of totalYieldLastYear and totalYieldCurrYear\ncurrentOutput|current output of the system\nmaxPeakOutputDay|the peak output of the day\ninternalTemperature|the inverter's internal temperature\ncurrentState|the inverter's current operating state\ninverter| subnode containing relevant information regarding the inverter's Modbus configuration\nmaxPeakTime|the time of inverter's peak\n\nWhen creating a first configuration file, all keys but the inverter key can be omitted since **mbpv** creates them for you. \n\n### Inverter\n\n``` json\n    \"inverter\": {\n      \"name\": \"SUNNY BOY 3.0\",\n      \"host\": \"sunny-boy-30\",\n      \"port\": 502,\n      \"unitId\": 1,\n      \"maxOutput\": 3000\n    },\n```\nKey | Value \n----|-------\nname | Name\nhost | IP address or hostname\nport | Modbus-TCP port (default: 502)\nunitId | Modbus unit id\nmaxOutput | maximum output of the inverter in watts\n\n### PVOutput.org\n\nIf you have added your PV system to [pvoutput.org](https://www.pvoutput.org/), you can add a respective node containing your systemId and your [apiKey](https://www.pvoutput.org/help.html#api). Since this node is removed from the [shared dictionary](https://github.com/jobe3774/raspend#how-to-use-the-http-interface) during runtime, it will not be exposed via HTTP.\n\n``` json\n  \"PVOutput.org\": {\n    \"apiKey\": \"secret-api-key\",\n    \"systemId\":  1234567890\n  }\n```\n\n## Usage\n\nIf not done yet, install [raspend](https://github.com/jobe3774/raspend) first:\n```\n$ pip3 install raspend\n```\nPlease see *requirements.txt* for more information about other dependencies.\n\nStart **mbpv** as follows:\n```\n$ python3 mbpv.py --port=8080 --config=./mbpv_config.json --peaklog=./peaks.csv\n```\nParameter|Description\n---|---\n--port | the port number raspends HTTP server should listen on (required)\n--config | path to the configuration file (required)\n--peaklog | path to a file where to log the daily peak output as comma separated values (required) \n\nThen open your favourite browser and type:\n```\nhttp://localhost:8080/data\n```\nYou get a JSON response, which contains most of the above values, extended by a node \"Suntimes\" (explained below).\n\n``` json\n{\n  \"Unit\": {\n    \"startUp\": \"2019-02-27\",\n    \"location\": {\n      \"longitude\": 6.0838868,\n      \"latitude\": 50.7753455\n    },\n    \"expectedYieldKWHperKWP\": 925,\n    \"peakOutputInWP\": 6270\n  },\n  \"Inverters\": [\n    \"sunnyboy1\",\n    \"sunnyboy2\"\n  ],\n  \"sunnyboy1\": {\n    \"totalYieldLastYear\": 0,\n    \"inverter\": {\n      \"name\": \"SUNNY BOY 3.0\",\n      \"host\": \"sunny-boy-30\",\n      \"port\": 502,\n      \"unitId\": 1,\n      \"maxOutput\": 3000\n    },\n    \"maxPeakOutputDay\": 155,\n    \"totalYieldCurrYear\": 2763865,\n    \"dayYield\": 968,\n    \"totalYield\": 2763865,\n    \"currentOutput\": 155,\n    \"internalTemperature\": 34.5,\n    \"currentState\": \"ok\",\n    \"maxPeakTime\": \"14:23\"\n  },\n  \"sunnyboy2\": {\n    \"totalYieldLastYear\": 0,\n    \"inverter\": {\n      \"name\": \"SUNNY BOY 3.6\",\n      \"host\": \"sunny-boy-36\",\n      \"port\": 502,\n      \"unitId\": 1,\n      \"maxOutput\": 3600\n    },\n    \"maxPeakOutputDay\": 170,\n    \"totalYieldCurrYear\": 3031643,\n    \"dayYield\": 1064,\n    \"totalYield\": 3031643,\n    \"currentOutput\": 169,\n    \"internalTemperature\": 35.8,\n    \"currentState\": \"ok\",\n    \"maxPeakTime\": \"14:23\"\n  },\n  \"Suntimes\": {\n    \"today\": [\n      1575184500,\n      1575199500,\n      1575214440\n    ],\n    \"yesterday\": [\n      1575098040,\n      1575113040,\n      1575128040\n    ],\n    \"tomorrow\": [\n      1575271020,\n      1575285900,\n      1575300780\n    ]\n  }\n}\n``` \n### Suntimes\n\nThis node has three subnodes *today*, *yesterday* and *tomorrow*, all containing an array of three unix timestamps, which are the times for sunrise, sun's upper culmination for the given location (see [*Unit*](https://github.com/jobe3774/mbpv#unit)) and sunset. The timestamps are in UTC.\n\nHere you can see a screenshot of the frontend I wrote for displaying the data collected by mbpv.\n\n![pv_display.png](./images/pv_display.png)\n\n# License\n\nMIT. See LICENSE file.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjobe3774%2Fmbpv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjobe3774%2Fmbpv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjobe3774%2Fmbpv/lists"}