Code Monkey home page Code Monkey logo

mate3's Introduction

Outback Mate 3 & 3s Python library & command line interface

PyPI version

This Python library aims to provide complete support for all Outback devices connected to a Mate3/Mate3s (or AXS port?) via Modbus. You can:

  • Read values in Python - and then do whatever you want with them e.g. monitoring/alerting/dynamic power management etc.
  • Write values - i.e. control your Outback system with Python.
  • (Hopefully) avoid ever having to know about Modbus at all. Just use the Python API or the CLI.
  • (Hopefully) get access to the full Outback spec in a 'user friendly' form. You don't need to know about the magic numbers in Enums or Bitfields (or the SunSpec), or how to interpret fault codes, and nor do you have to worry about twos-complements and other such things.
  • Co-develop without giving access to your system. That is, you can 'dump' a snapshot of your system and others can then interact with it (within reason) as if it were a real Mate3 over Modbus - which is great for testing/debugging/etc.

Tested on Python 3.7. May work on 3.6.

Installation

The recommended installation is as follows:

pip install mate3

After this you should be able to run the mate3 command. To access your Mate it must be connected to your local network using its ethernet port.

Background info you probably should know ...

Reading this will help you understand this libary and how to interact with your Mate.

Modbus

Hopefully, you don't need to worry about Modbus at all - this library should abstract that away for you. The key thing to note is that Modbus is a communication protocol, and this library works by interacting with the Mate3 physical devices using synchronous messages. So:

  • The information isn't 'live' - it's only the latest state since we last read the values. Generally, you should be calling read or write before/after any operation you make.
  • Don't over-communicate! If you start doing too many reads or writes you might brick the Modbus interface of your Mate (requiring a reboot to fix). As a rule of thumb, you probably don't want to be reading more frequently than once per second (and even then, preferably only specific fields, and not the whole lot). Since it's a communication protocol (and it's not actually clear what the latency is inherent in the Mate), there's not much point reading faster that this anyway.
  • Given the above, you might want to use the caching options in the Mate3Client, which can allow you to completely avoid interacting with/bricking your Mate while you're developing code etc. It's really tedious having to restart it every time your have a bug in your code.
  • Weird things happen when encoding stuff into Modbus. Hopefully you'll never notice this, but if you see things where your -1 is appearing as 65535 then yeh, that may be it.

SunSpec & Outback & Modbus

You can check out the details of how Outback implements Modbus in ./mate3/sunspec/doc, but the key things to note are:

  • SunSpec is a generic Modbus implementation for distributed energy systems include e.g. solar. There's a bunch of existing definitions for what e.g. charge controllers, inverters, etc. should be.
  • Outback use these, but they have their own additional information they include - which they refer to as 'configuration' definitions (generally as that's where the writeable fields live i.e. things you can change). Generally, when you're using this library you might see e.g. charge_controller.config.absorb_volts. Here the charge_controller is the SunSpec block, and we add on a special config field which is actually a pointer to the Outback configuration block. This is to try to abstract away the implementation details so you don't have to worry about their being multiple charge controller things, etc.

Pseudo-glossary

Words are confusing. For now, take the below as a rough guide:

  • Field - this is a definition of a field e.g. absorb_volts is Uint16 with units of "Volts" etc.
  • Model - This is generally referring to a specific Modbus 'block' - which is really just a collection of fields that are generally aligned to a specific device e.g. an inverter model will have an output KWH field, which a charge controller model won't. (Again, it's confusing here as Outback generally have two models per device.) In the case above charge_controller represents one (SunSpec) model, and charge_controller.config another (Outback) model.
  • Device - this is meant to represent a physical device and is basically our way of wrapping the Outback config model with the SunSpec one.
  • FieldValue - this is kind of like a Field but with data (read from Modbus) included i.e. "the value of the field". It includes some nice things too like auto-scaling variables ('cos floats aren't a thing) and simple read or write APIs.

More documentation?

At this stage, it doesn't exist - the best documentation is the code and the examples, though this only works well for those who know Python. A few other quick tips:

  • Turn intellisense on! There's a bunch of typing in this library, so it'll make your life much easier e.g. for finding all the fields accessible from your charge controller, etc.
  • ./mate3/sunspec/models.py has all of the key definitions for every model, including all the fields (each of which has name/units/description/etc.). Error flags and enums are properly defined there too.

Using the library

More documentation is needed (see above), but you can get a pretty code idea from ./examples/getting_started.py, copied (somewhat) below.

# Creating a client allows you to interface with the Mate. It also does a read of all devices connected to it (via the
# hub) on initialisation:
with Mate3Client("...") as client:
        # What's the system name?
        mate = client.devices.mate3
        print(mate.system_name)
        # >>> FieldValue[system_name] | Mode.RW | Implemented | Value: OutBack Power Technologies | Read @ 2021-01-01 17:50:54.373077
        
        # Get the battery voltage. Note that it's auto-scaled appropriately.
        fndc = client.devices.fndc
        print(fndc.battery_voltage)
        # >>> FieldValue[battery_voltage] | Mode.R | Implemented | Scale factor: -1 | Unscaled value: 506 | Value: 50.6 | ...
         Read @ 2021-01-01 17:50:54.378941

        # Get the (raw) values for the same device type on different ports.
        inverters = client.devices.single_phase_radian_inverters
        for port, inverter in inverters.items():
            print(f"Output KW for inverter on port {port} is {inverter.output_kw.value}")
        # >>> Output KW for inverter on port 1 is 0.7
        # >>> Output KW for inverter on port 2 is 0.0

        # Values aren't 'live' - they're only updated whenever you initialise the client, call client.update_all() or
        # re-read a particular value. Here's how we re-read the battery voltage. Note the change in the last_read field
        time.sleep(0.1)
        fndc.battery_voltage.read()
        print(fndc.battery_voltage)
        # >>> FieldValue[battery_voltage] | Mode.R | Implemented | Scale factor: -1 | Unscaled value: 506 | Value: 50.6 | Read @ 2021-01-01 17:50:54.483401

        # Nice. Modbus fields that aren't implemented are easy to identify:
        print(mate.alarm_email_enable.implemented)
        # >>> False

        # We can write new values to the device too. Note that we don't need to worry about scaling etc.
        # WARNING: this will actually write stuff to your mate - see the warning below!
        mate.system_name.write("New system name")
        print(mate.system_name)
        # >>>  FieldValue[system_name] | Mode.RW | Implemented | Value: New system name | Read @ 2021-01-01 17:50:54.483986

        # All the fields and options are well defined so e.g. for enums you can see valid options e.g:
        print(list(mate.ags_generator_type.field.options))
        # >>> [<ags_generator_type.AC Gen: 0>, <ags_generator_type.DC Gen: 1>, <ags_generator_type.No Gen: 2>]

        # In this case these are normal python Enums, so you can access them as expected, and assign them:
        mate.ags_generator_type.write(mate.ags_generator_type.field.options["DC Gen"])
        # >>> ags_generator_type.DC Gen

Using the command line interface (CLI)

A simple CLI is available, with four main sub-commands:

  • read - reads all of the values from the Mate3 and prints to stdout in a variety of formats.
  • write - writes values to the Mate3. (If you're doing anything serious you should use the python API.)
  • devices - shows the connected devices.
  • dump - dumps all of the raw modbus values to a (JSON) file in a format compatible with CachingModbusClient which you can then share with others to help in debugging any problems you may have.

For each you can access the help (i.e. mate3 <cmd> -h) for more information.

Warnings

First, the big one:

WARNING! Please make sure you read the license before using any of the write functionality. You could easily damage your equipment by setting incorrect values (directly or indirectly).

In addition, there are other edges cases that may cause problems, mostly related to if a device is re-assigned a new port. For example, you have two inverters, read some values, then switch their ports over in the Hub before writing some values - which may now go to the 'wrong' one. For now, it's safest not to do that, unless you restart the Mate3Client each time. On that note, the recommended approach if you need to poll over time is to recreate the Mate3Client on every poll (as opposed to re-using one), as that'll help avoid these (or other) issues. There are exceptions to this rule, but you should know why you're breaking it before you do so.

Troubleshooting

Some ideas (which can be helpful for issues)

Set log-level to DEBUG

See mate3 -h for the CLI, otherwise the following (or similar) for python code:

from loguru import logger
logger.remove()
logger.add(sys.stderr, level="DEBUG")

List the devices

$ mate3 devices --host ...
name                                               address    port
----                                               -------    ----
Mate3                                              40069      None
ChargeController                                   40986      4
ChargeControllerConfiguration                      41014      4
...

Are they all there?

Create a dump of the raw modbus values

See mate3 dump -h. You can send the resulting JSON file to someone to help debug. (Just note that it includes all the data about the Mate, e.g. any passwords etc.)

Writing data to Postgres

See ./examples/postgres_monitor/README.md

Contributing

See ./CONTRIBUTING.md

Credits

This was originally a heavily refactored version of basrijn's Outback_Mate3 library, though has largely been completely rewritten since. Thanks anyway basrijn!

mate3's People

Contributors

adamcharnock avatar kodonnell avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

mate3's Issues

Consistent field naming system

The problem

Field are currently named and referenced very inconsistently. For example:

mate3

mate3 output humanifys device names, and displays field names nested below:

Screenshot 2020-03-02 at 23 47 21

mate3_write

mate3_write uses a . notation:

Screenshot 2020-03-02 at 23 48 27

API

The programmatic API requires one to reference the field via the Parser class:

from mate3.parsers import ChargeControllerParser

values = client.get_values(
    ChargeControllerParser.battery_current, 
    ChargeControllerParser.battery_voltage
)

The solution

The solution needs to:

  • Be readable when printed to the terminal
  • Be useable as python code
  • be able to identify a specific device, even when multiple of the same device are connected.

I therefore propose the following:

client.{device_name_as_plural}[{device_number}].{field_name}

Example:

client.charge_controllers[0].absorb_volts

We can also enhance this further. Currently, for example, ChargeControllerParser and ChargeControllerConfigurationParser are two separate devices. This doesn't really make conceptual sense. Using the above scheme, this would appear as:

client.charge_controllers[0].field_name
client.charge_controller_configs[0].field_name

Instead, this would be nicer:

client.charge_controllers[0].field_name
client.charge_controllers[0].config.field_name

Additionally, there can only be one of some devices. These have not port number. For example, mate3.smtp_account_name. These cases would be used without the pluralisation, and without the indexing. For example:

client.mate3.smtp_account_name

Tasks

  • Move field definitions away from the parser classes
  • Refactor client API to support new scheme
    • Reading
    • Writing
  • Support ancillary access via original outback field names
  • Update mate3 to use this output format (maybe with some nice colours)
  • Update mate3_write to use this output format (maybe with some nice colours)
  • Generate markdown document of all fields (include original output field name)

OutBack System Control Block - zero value for some registries

Zero values returned by the code for some registries in OutBack System Control Block - DID 64120.

ex:
OB_Bulk_Charge_Enable _Disable
OB_Inverter_AC_Drop_Use
OB_Set_Inverter_Mode
OB_Grid_Tie_Mode
OB_Set_Inverter_Charger_Mode

All of these are "enumerated" in the "Application Note SunSpec Data Blocks and the AXS Port"
These registries are important for various automation -- start EQ, drop AC and so on.

Store raw registers in field value

Might be useful for debugging (and exporting to JSON etc.) if the raw bytes were visible.

  • Add new _registers attribute or similar and ensure it's populated.
  • Add these registers as hex bytes or similar to the JSON output. (And the address too, if that isn't already.)

AttributeError: 'Mate3' object has no attribute 'get_device_blocks'

Tried to use the python3 like in the example provided and i get this error when tried to get all values for a specific device or specific value.

my code:
from mate3 import mate3_connection
from mate3.parsers import ChargeControllerParser, ChargeControllerConfigurationParser
from mate3.base_structures import Device

host = '192.168.0.150'
port = 502
with mate3_connection(host, port) as client:
all_blocks = client.all_blocks()
for block in all_blocks:
print(block)
values = client.get_device_blocks(Device.charge_controller)
print(list(values))

[question] Performance Speed

I interesting to know how long Mate3 modbus is busy when we'll do a read() -- full set of values
Did you perform any speed test?

Clearer outputs for different field types in the CLI and in a JSON export

It is difficult to understand why is not the same approach between raw_value and value ?

From my understanding raw_value is coming directly from mate3 "as is" without any conversion and value is after conversion, like "ready to use" ex. Case 3 with voltage. Which is good!
Now, when we are looking on Case 1 raw_value it is not "as is" and value is not "ready to use".
If I wanted to use JSON data, I would have expected something like that:
raw_value: 1
value: "Enabled"

Case 1
"enable_dhcp": {
"implemented": true,
"scale_factor": null,
"raw_value": "<enable_dhcp.DHCP Enabled: 1>",
"value": "<enable_dhcp.DHCP Enabled: 1>"

Case 2
"tcpip_address": {
"implemented": true,
"scale_factor": null,
"raw_value": "192.168.0.150",
"value": "192.168.0.150"

Case 3
"hbx_grid_connect_voltage": {
"implemented": true,
"scale_factor": -1,
"raw_value": 492,
"value": 49.2

export to json not working

0.5.3 export to json was ok, starting with 0.6.0 give below error

pi@raspberrypi:~ $ mate3 read --host 192.168.0.150 -f json >mate3_060.json

2021-01-10 19:35:24.682 | WARNING  | mate3.api:_read_model:165 - Error reading field gateway_type - so setting as not implemented. Message: 3 is not a valid gateway_type
2021-01-10 19:35:24.701 | WARNING  | mate3.api:_read_model:165 - Error reading field inverter_operating_mode - so setting as not implemented. Message: 12 is not a valid inverter_operating_mode
Traceback (most recent call last):
  File "/home/pi/.local/bin/mate3", line 8, in <module>
    sys.exit(main())
  File "/home/pi/.local/lib/python3.7/site-packages/mate3/main.py", line 199, in main
    read(client, args)
  File "/home/pi/.local/lib/python3.7/site-packages/mate3/main.py", line 59, in read
    print(json.dumps(devices, indent=indent))
  File "/usr/lib/python3.7/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python3.7/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.7/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python3.7/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type FieldValue is not JSON serializable

Developer docs

Not urgent, but it'd be good to add some developer documentation that includes:

  • Basics of modbus
  • SunSpec (and how it differs to Outback etc.)
  • Specifics of Outback spec e.g. the 'configuration' modules, etc.
  • Description of the code and generally how it works. Even I'll admit it's a bit messy at the moment, including the auto-generated stuff. With models/values/devices/etc. nomenclature is a bit confusing.

On write, fields are still marked as dirty

Current behaviour after assigning a new value is for the old value to stay present, and the field marked as dirty with an internal _value_to_write variable holding the new value. Then, on client.write() the _value_to_write is written - but that's it, and it's still marked as dirty etc.

I think this leaving as dirty was deliberate in that who knows what value is actually on the device until we re-read it - the write could have failed, etc. So, the idea was that after writing you should probably do a client.read() to get the new value. However, as it stands, there's no state indicating the three different scenarios:

  • read: The value matches what's on the device, at the time of the read.
  • dirty: waiting to write: We've assigned a new value but we haven't written it yet.
  • dirty: written but write unverified: We've tried to write, but haven't read it to check. (When we do, it'll go back to the read state.)

The other option is (optionally) auto-committing (like a database) so as soon as you set a value it automatically writes the value and then re-reads it (and throws an error if the write didn't result in the correct value). This would probably be the safest in the sense of:

  • Easiest to understand for newcomers - behaves as expected.
  • Less likely to get into weird problems when you have multiple fields e.g. you write one field depending on another, but you forgot to write the former so it didn't use the dirty value you thought it would, etc.

The main downside is it'd be slower (?) for a large number of sequential writes. But that seems a pretty rare use case, so I'd be willing to ignore that for now. (And, if it becomes an issue, we could always implement autocommit=False.)

Any preferences @adamcharnock ? I don't imagine this is particularly high priority at the moment.

Changing API?

Just wondering about some possible changes, as below. Note that it wouldn't make sense to make all of these - some remove the need for others.

1. Parser -> Device

Just thinking that ChargeControllerParser confuses me - it's somewhat internal logic, whereas as a user I want to think about ChargeController as a device. So instead of

from mate3.parsers import ChargeControllerParser
values = client.get_values(
    ChargeControllerParser.battery_current, 
    ChargeControllerParser.battery_voltage
)

I'd be less confused with

from mate3.devices import ChargeController
values = client.get_values(
    ChargeController.battery_current, 
    ChargeController.battery_voltage
)

2. Remove use of enums/lookups and use objects for devices

For example, instead of

client.get_values(ChargeControllerParser.battery_current)

What do you think about?

client.charge_controllers[0].battery_current

i.e.

  • automatically have the client read the charge controller into an object, and
  • use the native __getattr__ instead of reimplementing this as get_values. And we could ensure the appropriate scaling is applied before returning to the user too, actually.

Similarly, it makes writing easier/cleaner. Instead of

client.set_value(
    field=ChargeControllerConfigurationParser.absorb_volts,
    value=330,
    port=3
)

we could have

client.charge_controllers[0].absorb_volts = 33 # NB: internally we scale it appropriately before sending to modbus
client.write() # (or we could have an 'autocommit' functionality)
)

This is similar to how pySunSpec do it.

Remove modbus references (at least at high level)

For example, allow the user to interact without knowing what blocks are. If I include the changes from 2. and this, the main example from the readme could look like this:

from mate3 import mate3_connection

host = '192.168.0.123'
port = 502

with mate3_connection(host, port) as client:
    client.read()
    print(client.charge_controllers[0].battery_current)
    print(client.charge_controllers[0].battery_voltage)
    # Writing data
    client.charge_controllers[0].absorb_volts = 33
    client.write()

(Note that I've merged the ChargeController and ChargeControllerConfiguration.)

Thoughts? I'm just thinking that for users like me, who just want to read (and maybe write) values, we try to make it as easy as possible. There are some minor things to sort out, but if you like the general idea, I can have a crack at a PR?

Use pymodbus decoding

This is a much cleaner way of doing decoding to Int16s etc. Use this as less maintenance and simpler code.

Need to think a bit ... may be able to get rid of Field._from_registers and Field._to_registers now since they'll largely just be e.g. decoder.decode_16bit_int etc. May be able to just add a read_contiguous_fields method to the modbus client which just does all the nice things for you, including creating FieldValues. Anyway, worth thinking through, especially if it makes the code internals nicer.

Bugs in some Outback fields?

Firstly, these:

2020-12-31 17:10:15.475 | WARNING  | mate3.api:_read_model:153 - Error reading field input_support - so setting as not implemented. Message: 54 is not a valid input_support
2020-12-31 17:10:15.475 | WARNING  | mate3.api:_read_model:153 - Error reading field grid_tie_enable - so setting as not implemented. Message: 255 is not a valid grid_tie_enable
2020-12-31 17:10:15.487 | WARNING  | mate3.api:_read_model:153 - Error reading field input_support - so setting as not implemented. Message: 54 is not a valid input_support
2020-12-31 17:10:15.487 | WARNING  | mate3.api:_read_model:153 - Error reading field grid_tie_enable - so setting as not implemented. Message: 255 is not a valid grid_tie_enable

Secondly, for UInt32s. The way we're doing it is "right" in that it correctly gets the SunSpecHeaderModel DID. That is

val = (registers[0] << 16) | registers[1]

However, some fields are wrong e.g. todays_minimum_battery_time and todays_maximum_battery_time - I'm 99% confident they fields are the wrong way round and should be read this way

val = (registers[1] << 16) | registers[0]

As they give much more realistic UTC timestamps. However, I'm assuming that's because the Outback implementation is wrong - @adamcharnock do you have a contact I can follow up with? There are possibly some other issues here and there too, which I can dig into. Luckily, nothing major by the looks.

Using the library (enhancement)

Again thanks yor great work.

I'm wonderng if possible to update the documentation of using the library with more code examples, covering usage of Fields, Field_values, models, devices -- read and write syntax

  • how to read all Mate3 data in one shot and export them in different formats (JSON) human readable ( similar with CLI commands)
  • how to handle multiple inverters and multiple chargers in the system read write
    example:
    #Get the (raw) values for the same device type on different ports.
    inverters = client.devices.single_phase_radian_inverters

what about reading of inverter on port 1 and writing on the inverter port 1?

Tidy up the use of `raw_value`

As per #22 there's a bit of potential confusion around the semantics raw_value. That is, it could mean:

  • (My original intention) - the 'raw' value after doing SunSpec conversion of bytes to a value (e.g. a Uint16) i.e. after calling from_registers.
  • (The interpretation from #22) - the 'raw' integer value of an enum.

That's my bad. Realistically, it's only used for scaling decimal fields, so I think the answer here is to refactor the code so that a 'normal' FieldValue doesn't have all this scaling stuff. Maybe create a ScaledFieldValue? Need to think about that. Then ensure there's only one value thing per (Scaled)FieldValue (not two as we currently have value and raw_value).

Mate3Parser writing

Tried to set value for Mate3 with:
client.set_value(field=Mate3Parser.sched_3_ac_mode, value=4, port=0)
As Mate3 do not have any port field, I put port=0 hoping that that will work...
Below the traceback of the error:

Traceback (most recent call last):
File "C:\Users\chine\AppData\Local\Programs\Thonny\lib\site-packages\thonny\backend.py", line 1164, in _execute_prepared_user_code
exec(statements, global_vars)
File "S:\Development\Python_Scripts\Examples\Mate3_GitHubModule\mate3_Modbus_githubModule_write.py", line 24, in
client.set_value(field=Mate3Parser.sched_3_ac_mode,value=4, port=0)
File "C:\Users\chine\AppData\Roaming\Python\Python37\site-packages\mate3\api.py", line 187, in set_value
"Cannot set values for devices which lack a 'port_number' field. "
Exception: Cannot set values for devices which lack a 'port_number' field. Please raise an issue in GitHub if you see this, including details of the device you are trying to set values on.

Use native int to_bytes / from_bytes instead of FixedInt

As per title. Won't change functionality, just removes a dependency.

E.g.

>>> x = (-1).to_bytes(2, 'little', signed=True)
>>> x
b'\xff\xff'
>>> int.from_bytes(x, byteorder='little', signed=True)
-1
>>> int.from_bytes(x, byteorder='little', signed=False)
65535

How to write fields with mate3 cli?

Hi! I now got the mate3 cli working after some debugging and fixing issues in the code (see my pull request with the modifications I did)

It's not yet entirely clear how can I should write values to the mate3 using the mate3 cli

I'm trying to switch on the AUX port on our secondary inverter

This is what I've got:
mate3 write --set single_phase_radian_inverters[2].config.aux_control=<what goes here?> --host <ip>

The code does an eval() on the provided value, but it's not entirely clear what should I use as the value?

When I import from mate3.sunspec.models import RadianInverterConfigurationModel in mate3/main.py and use RadianInverterConfigurationModel.aux_control.options.On I can switch on the AUX port. Are there just some imports missing and is the way it was intended to work, or should I do something else?

Poetry install error

I've got an install error when following the instructions in CONTRIBUTING.md on macOS 12.2.1

Fixed it by updating the required black version in pyproject.toml to ^22.1.0

Read & export all data in 0.6.2

Hi,

In previous versions 0.4.0, was possibility in python to extract all data from Mate3 and export in a JSON file.
The code was like this:

from mate3.api import mate3_connection
from mate3.parsers import ChargeControllerParser, ChargeControllerConfigurationParser
from mate3.base_structures import Device
import json
import time

with mate3_connection ('192.168.0.150') as client:

blocks = client.all_blocks()

block_dicts = [b._asdict() for b in blocks]
for block_dict in block_dicts:
    block_dict['device'] = block_dict['device'].name

print(json.dumps(block_dicts))
file = open("mate3allblocks.json","w")
file.write(json.dumps(block_dicts))
file.close()

Do we have something similar in 0.6.2 ?

Mate3Parser sched_x_ac_mode - disabled mode can not be set

There is a conflict in reading "Disabled" and "Generator" ac_mode - both are reported with 0.
coding of OutBack_Schedule modes are below:
Generator # 0
Support # 1
GriedTied # 2
UPS # 3
Backup # 4
MiniGrid # 5
GridZero # 6
Disabled # -1 in fact is (65535)

Basically is impossible to write corresponding "Disabled" mode.
Issue potential affect also other parsers where ac _mode is present ex.: RadianInverterConfigurationParser.

client.read() - help needed

just installed new version 0.5.0 and tried to run the python script from example (short version below) :

from loguru import logger
import sys
import time
from mate3.api import Mate3Client

logger.remove()
logger.add(sys.stderr, level="DEBUG")

with Mate3Client("192.168.0.150") as client:
    client.read()

unfortunately there are some errors, see below
output.txt
my system: mate3s / 2 inverters VFXR /2 controllers/FNDC

mate3 command not installed (on Windows?)

I did not manage to use CLI as described ex mate3 -h.
I used instead:
python C:\Users\chine\Downloads\mate3-master\mate3-master\mate3\main.py --host 192.168.0.150 --format json
Maybe should be better explained.

can not get cli to run

Thank you for this work. I am very excited to use it. I attempting to connect to a mate3s.

C:\Users\parker>mate3 devices -host 10.220.10.44
Traceback (most recent call last):
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.496.0_x64__qbz5n2kfra8p0\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.496.0_x64__qbz5n2kfra8p0\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\parker\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\Scripts\mate3.exe\__main__.py", line 4, in <module>
  File "C:\Users\parker\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\mate3\main.py", line 13, in <module>
    from mate3.api import Mate3Client
  File "C:\Users\parker\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\mate3\api.py", line 8, in <module>
    from mate3.devices import DeviceValues
  File "C:\Users\parker\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\mate3\devices.py", line 10, in <module>
    from mate3.sunspec.models import (
  File "C:\Users\parker\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\mate3\sunspec\models.py", line 22, in <module>
    class CCconfigFaultsFlags(BitfieldDescriptionMixin, IntFlag):
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.496.0_x64__qbz5n2kfra8p0\lib\enum.py", line 131, in __prepare__
    member_type, first_enum = metacls._get_mixins_(cls, bases)
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.496.0_x64__qbz5n2kfra8p0\lib\enum.py", line 523, in _get_mixins_
    member_type = _find_data_type(bases) or object
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.496.0_x64__qbz5n2kfra8p0\lib\enum.py", line 511, in _find_data_type
    raise TypeError('%r: too many data types: %r' % (class_name, data_types))
TypeError: 'CCconfigFaultsFlags': too many data types: [<class 'mate3.sunspec.fields.BitfieldDescriptionMixin'>, <class 'int'>]

All "N/A" ports, and no devices appearing in mate3_write --list-fields other than Mate

Using the CLI commands, I got a message saying I should raise an issue in GitHub, so here I am.

I have a Mate3s with ~9 month old firmware, on a Hub10, 2x Radian GS8048a, 3x FM-100, and FNDC. All data interfacing functions of the Mate seem to work normally.

I'm happy to send the entirety of what I see in the terminal, but it's pretty straightforward. When I first run mate3_write ... --list-fields, it starts with 25 lines of the following:

20200828 01:51:55 Unknown device type with device ID 120

Then, it lists the mate3 and outback_system_control with "Hub ports" showing N/A, and all of the following fields show N/A for the ports. There are no fields listed for any of the devices on the hub (inverters, charge controllers, FNDC).

=================================== Devices ====================================
DEVICE NAME HUB PORT(S)
mate3 N/A
outback_system_control N/A
==================================== Fields ====================================
FIELD NAME HUB PORT(S)
mate3.ags_24_hour_start_mode N/A 0=Disabled, 1=Enabled
mate3.ags_24_hour_start_voltage N/A Twenty Four Hour AGS Start Voltage
mate3.ags_2_hour_start_mode N/A 0=Disabled, 1=Enabled
mate3.ags_2_hour_start_voltage N/A Two Hour AGS Start Voltage

...etc.

Obviously, I can't write to the fields, and in trying to do so, I learned that I:

Cannot set values for devices which lack a 'port_number' field. Please raise an issue in GitHub if you see this, including details of the device you are trying to set values on.

My main goal is to be able to change the AC mode on the master inverter, although there are a number of Mate-related fields that would also be nice to be able to change. Thanks for taking a look.

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.