Package: mate3
Outback Mate 3 & 3s Python library & command line interfaceThis 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.InstallationThe recommended installation is as follows:pipinstallmate3After this you should be able to run themate3command. 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.ModbusHopefully, 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 callingreadorwritebefore/after any operation you make.Don't over-communicate! If you start doing too manyreads orwrites 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 theMate3Client, 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-1is appearing as65535then yeh, that may be it.SunSpec & Outback & ModbusYou 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 thecharge_controlleris the SunSpec block, and we add on a specialconfigfield 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-glossaryWords are confusing. For now, take the below as a rough guide:Field- this is a definition of a field e.g.absorb_voltsisUint16with 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 abovecharge_controllerrepresents one (SunSpec) model, andcharge_controller.configanother (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 aFieldbut 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 simplereadorwriteAPIs.More documentation?At this stage, it doesn't exist - the best documentation is the code andthe 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.pyhas 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 libraryMore 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:withMate3Client("...")asclient:# What's the system name?mate=client.devices.mate3print(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.fndcprint(fndc.battery_voltage)# >>> FieldValue[battery_voltage] | Mode.R | Implemented | Scale factor: -1 | Unscaled value: 506 | Value: 50.6 | ...Read@2021-01-0117:50:54.378941# Get the (raw) values for the same device type on different ports.inverters=client.devices.single_phase_radian_invertersforport,inverterininverters.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 fieldtime.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 GenUsing 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 withCachingModbusClientwhich 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.WarningsFirst, the big one:WARNING!Please make sure you readthe licensebefore using any of thewritefunctionality. 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 theMate3Clienteach time. On that note, the recommended approach if you need to poll over time is to recreate theMate3Clienton 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.TroubleshootingSome ideas (which can be helpful for issues)Set log-level to DEBUGSeemate3 -hfor the CLI, otherwise the following (or similar) for python code:fromloguruimportloggerlogger.remove()logger.add(sys.stderr,level="DEBUG")List the devices$mate3devices--host...
nameaddressport
---------------
Mate340069None
ChargeController409864ChargeControllerConfiguration410144...Are they all there?Create a dump of the raw modbus valuesSeemate3 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 PostgresSee./examples/postgres_monitor/README.mdContributingSee./CONTRIBUTING.mdCreditsThis was originally a heavily refactored version ofbasrijn's Outback_Mate3 library, though has largely been completely rewritten since. Thanks anyway basrijn!