SunSpec

Client

async with sundog.client.open_client(host, port)[source]

Open a SunSpec Modbus TCP connection to the passed host and port.

Parameters
  • host (str) – The host name or IP address.

  • port (int) – The port number.

Yields

The SunSpec client.

Return type

AsyncIterator[Client]

class sundog.client.Client(modbus_client, protocol, sunspec_device)[source]

Bases: object

A SunSpec Modbus TCP client using trio support in pymodbus for communication and pysunspec2 for loading models and holding the local cache of the data. The existing communication abilities of the pysunspec2 objects are left intact but should not be used.

__getitem__(item)[source]

SunSpec models are accessible by indexing the client using either the model number or model name.

model_1 = client[1]
model_common = client["common"]
assert model_1 is model_common
Return type

SunSpecModbusClientModel

Returns

The requested model.

modbus_client: pymodbus.client.asynchronous.trio.TrioModbusTcpClient

The Modbus TCP client used for communication.

protocol: pymodbus.client.common.ModbusClientMixin

The Modbus client protocol.

sunspec_device: sunspec2.modbus.client.SunSpecModbusClientDevice

The SunSpec device object that holds the local data cache and model structures.

await scan()[source]

Scan the device to identify the base address, if not already set, and collect the model list. This also populates all the data.

Return type

None

await read_registers(address, count)[source]

Read from the specified sequential register range in the device. Based on the 16-bit Modbus register size, the data in the returned bytes is in 2-byte chunks with each having a big-endian byte order. The local data is not updated.

Parameters
  • address (int) – The first register to read.

  • count (int) – The total number of sequential registers to read.

Return type

bytes

Returns

The raw bytes read from the device.

Raises

sundog.ModbusError – When a Modbus exception response is received.

await read_point(point)[source]

Read the passed point from the device and update the local data.

Parameters

point (SunSpecModbusClientPoint) – The SunSpec point object to read.

Return type

Union[float, int]

Returns

The new computed value of the point.

Raises

sundog.ModbusError – When a Modbus exception response is received.

point_address(point)[source]

Calculate the start address of a given SunSpec point.

Parameters

point (SunSpecModbusClientPoint) – The SunSpec point object to read.

Return type

int

Returns

The address of the first register of the point.

await write_registers(address, values)[source]

Write to the specified sequential register range in the device. Based on the 16-bit Modbus register size, the data in the passed bytes should in 2-byte chunks with each having a big-endian byte order. The local data is not updated.

Parameters
  • address (int) – The first register to write.

  • count – The total number of sequential registers to write.

Return type

None

Returns

The raw bytes to be written to the device.

Raises

sundog.ModbusError – When a Modbus exception response is received.

await write_point(point)[source]

Write the passed point from the local data to the device.

Parameters

point (SunSpecModbusClientPoint) – The SunSpec point object to write.

Raises

sundog.ModbusError – When a Modbus exception response is received.

Return type

None

Server

class sundog.server.Server(slave_context, server_context, identity)[source]

Bases: object

A SunSpec Modbus TCP server using trio support in pymodbus for communication and pysunspec2 for loading models and holding the local cache of the data. The actual TCP server can be launched using Server.tcp_server().

await nursery.start(
    functools.partial(
        trio.serve_tcp,
        server.tcp_server,
        host="127.0.0.1",
        port=0,
    ),
)
__getitem__(item)[source]

SunSpec models are accessible by indexing the client using either the model number or model name.

model_1 = server[1]
model_common = server["common"]
assert model_1 is model_common
Parameters

item (Union[int, str]) – The integer or string identifying the model.

Return type

SunSpecModbusClientModel

Returns

The requested model.

slave_context: sundog.server.SunSpecModbusSlaveContext

The single slave context to be served by this server. This is backed by the SunSpec device object.

server_context: pymodbus.datastore.context.ModbusServerContext

The datastore for this pymodbus server. Presently only a single slave context is supported.

identity: pymodbus.device.ModbusDeviceIdentification

The identity information for this Modbus server.

classmethod build(model_summaries)[source]

Build the server instance based on the passed model summaries. Any per-point or bulk data update must be done separately.

Parameters

model_summaries (Sequence[ModelSummary]) – The models which you want the server to provide.

Return type

Server

Returns

The instance of the server datastore pieces.

await tcp_server(server_stream)[source]

Handle serving over a stream. See Server for an example.

Parameters

server_stream (SocketStream) – The stream to communicate over.

Return type

None

class sundog.server.ModelSummary(id, length)[source]

Bases: object

A model can be summarized by its ID and length. While models of fixed length would not need the length provided, those with repeatable blocks need a length to indicate the number of repetitions of the repeating block.

id: int

The integer model ID.

length: int

The model length inclusive of the fixed and repeating blocks and exclusive of the model’s ID and length header.

class sundog.server.SunSpecModbusSlaveContext(sunspec_device)[source]

Bases: pymodbus.interfaces.IModbusSlaveContext

A pymodbus slave context that is backed by the pysunspec2 device object.

sunspec_device: sunspec2.modbus.client.SunSpecModbusClientDevice

The pysunspec2 device object use for local storage of the SunSpec data.

getValues(fx, address, count=1)[source]

See pymodbus.interfaces.IModbusSlaveContext.getValues().

Return type

bytearray

setValues(fx, address, values)[source]

See pymodbus.interfaces.IModbusSlaveContext.setValues().

Return type

None

validate(fx, address, count=1)[source]

See pymodbus.interfaces.IModbusSlaveContext.validate().

Return type

bool

class sundog.server.PreparedRequest(data, slice, offset_address, bytes_offset_address)[source]

Bases: object

Holds some common bits used in serving a request.

data: bytearray

The entire block of registers. Each register is a 2-byte chunk stored in big-endian byte order. The first element is the high byte of the server’s register located at the base address.

slice: slice

The slice covering the bytes of the registers to be operated on.

offset_address: int

The offset in 16-bit/2-byte registers relative to the server’s base address.

bytes_offset_address: int

The offset in bytes relative to the server’s base address.

classmethod build(base_address, requested_address, count, all_registers)[source]

Build the instance based on the passed raw request information.

Parameters
  • base_address (int) – The SunSpec base register address.

  • requested_address (int) – The requested address.

  • count (int) – The requested register count.

  • all_registers (bytes) – The raw register data for all models.

Return type

PreparedRequest

Returns

The prepared request information.