denpamusic/PyPlumIO

Some parameters must be float

denpamusic opened this issue · 4 comments

Hi,

Thermostat hysteresis is float but here we have int, is this behavior good?

that same by mixer.insensitivity, this value in ecomax is float but here is int

Originally posted by @entmor in #8 (comment)

Having parameters as int is fine, since they are actually transmitted as integer multiplied by 10 and not a real float. However for usability sake, I'll consider conversion by dividing them by 10 for the next release.

Hi,

thx for your answer and job ;)

ok. for me INT is ok but some data like 'day_target_temp' we change as float number, so maybe better set value as float, when this data in ecoster/ecomax is showing(on display ;)) as float

You're right. After thinking about it, I've also ultimately decided to rewrite the Parameter class to handle all such values as true floats.

There a lot of them actually even in ecoMAX parameters. For example heating_heat_curve parameter is also single-byte integer (char) which represents float multiplied by 10. day_target_temp that you mentioned is even more interesting, since it's actually a two-byte integer (ushort) also multiplied by 10 :)

If possible, could you please help me with one more thing, since you have a top of the line device, could you, please, run the code below and send me resulting ecomax_data.json file, either by attaching it in this issue or via the email. This code will collect the data for your device for 10 seconds, convert it to json format and dump it to the file. You can of course review file contents before sending and remove any sensitive information.

This will help me to find all parameters that must be converted to float, since I myself have a ecoMAX 350 which is pretty limited in features.

Thanks!

import asyncio
import json
from typing import Final

from pyplumio import open_serial_connection
from pyplumio.devices import BaseDevice

SECONDS: Final = 10
FILENAME: Final = "ecomax_data.json"


def _is_json_serializable(data) -> bool:
    """Check if data is json serializable."""
    try:
        json.dumps(data)
        return True
    except TypeError:
        return False


class DeviceDataEncoder(json.JSONEncoder):
    """Represents custom device data encoder."""

    def default(self, o):
        """Encode device data to json."""
        if isinstance(o, dict):
            o = {x: self.default(y) for x, y in o.items()}

        if isinstance(o, list):
            o = [self.default(x) for x in o]

        if isinstance(o, BaseDevice):
            o = self.default(o.data)

        if _is_json_serializable(o):
            return o

        return {"__type": str(type(o)), "repr": repr(o)}


async def main() -> None:
    """Open the ecoMAX connection and collect device data for some time,
    then dump it to the json file.
    """
    async with open_serial_connection(device="/dev/ttyUSB0") as connection:
        ecomax = await connection.get_device("ecomax")

        print(f"Collecting data for {SECONDS} seconds, please wait...")
        await asyncio.sleep(SECONDS)

        print(f"Saving collected data to {FILENAME}...")
        with open(FILENAME, "w", encoding="UTF-8") as file:
            file.write(json.dumps(dict(ecomax.data), cls=DeviceDataEncoder, indent=2))

        print("All done!")


asyncio.run(main())

With parameter descriptors, PyPlumIO can now handle floats. Here is an example of such a parameter. When received from the device fuel_calorific_value_kwh_kg parameter is converted to float by dividing it by ten, when setting this parameter, value will be automatically converted back to integer for device.