Example #1
0
async def clean_watthours_by_day(
    datapoints: t.AsyncIterator[DataPoint], ) -> CLEANED_DT_FLOAT:
    last_watthours = None
    last_date = None
    async for datapoint in datapoints:
        if datapoint.data is None:
            continue
        date = datapoint.collected_at.date()
        if date != last_date:
            # We have a new date
            watthours = ureg.Quantity(datapoint.data["magnitude"],
                                      datapoint.data["unit"])
            if last_watthours is not None and last_date is not None:
                midpoint = datetime.datetime.combine(last_date,
                                                     datetime.time(12, 0, 0))
                diff = watthours - last_watthours
                yield midpoint, diff.to(ureg.kilowatt_hours).magnitude
            last_watthours = watthours
            last_date = datapoint.collected_at.date()
    if last_watthours is not None and last_date is not None:
        watthours = ureg.Quantity(datapoint.data["magnitude"],
                                  datapoint.data["unit"])
        midpoint = datetime.datetime.combine(datapoint.collected_at.date(),
                                             datetime.time(12, 0, 0))
        diff = watthours - last_watthours
        yield midpoint, diff.to(ureg.kilowatt_hours).magnitude
    def value(self) -> t.Optional[t.Any]:
        if self.bt_addr is None:
            return None
        try:
            output: bytes = subprocess.check_output(
                [self.path, "-i", self.bt_addr],
                stderr=subprocess.STDOUT,
                timeout=15)
        except (subprocess.CalledProcessError, FileNotFoundError):
            return None

        lines = filter(None, output.split(b"\n"))
        found = {}
        for line in lines:
            start, value = line.rsplit(b"=", 1)
            start, key = start.rsplit(b" ", 1)
            found[key] = value

        try:
            yield_total = float(found[b"yield_total"][:-3].replace(b".", b""))
            power_dc_1 = int(found[b"power_dc_1"][:-1])
            power_dc_2 = int(found[b"power_dc_2"][:-1])
            if power_dc_1 > 1500 or power_dc_2 > 1500:
                return None
        except (ValueError, IndexError, KeyError):
            return None
        return ureg.Quantity(yield_total, "watt")
    def value(self) -> t.Optional[t.Any]:
        if self.bt_addr is None:
            raise PersistentSensorFailureError(
                "Inverter address not configured")
        try:
            output: bytes = subprocess.check_output(
                [self.path, "-i", self.bt_addr],
                stderr=subprocess.STDOUT,
                timeout=15)
        except subprocess.CalledProcessError as err:
            raise IntermittentSensorFailureError(
                "Failure communicating with inverter") from err
        except FileNotFoundError as err:
            raise PersistentSensorFailureError(
                "Inverter control software not installed") from err

        lines = filter(None, output.split(b"\n"))
        found = {}
        for line in lines:
            start, value = line.rsplit(b"=", 1)
            start, key = start.rsplit(b" ", 1)
            found[key] = value

        try:
            yield_total = float(found[b"yield_total"][:-3].replace(b".", b""))
            power_dc_1 = int(found[b"power_dc_1"][:-1])
            power_dc_2 = int(found[b"power_dc_2"][:-1])
            if power_dc_1 > 1500 or power_dc_2 > 1500:
                raise IntermittentSensorFailureError(
                    "Received corrupt data from inverter")
        except (ValueError, IndexError, KeyError) as err:
            raise IntermittentSensorFailureError(
                "Received incomplete data from inverter") from err
        return ureg.Quantity(yield_total, "watt")
async def clean_watthours_to_watts(
    datapoints: t.AsyncIterator[DataPoint],
) -> CLEANED_DT_FLOAT:
    last_watthours = None
    last_time = None
    async for datapoint in datapoints:
        if datapoint.data is None:
            continue
        time = datapoint.collected_at
        watthours = ureg.Quantity(datapoint.data["magnitude"], datapoint.data["unit"])
        if last_watthours:
            seconds_elapsed = (time - last_time).total_seconds()
            time_elapsed = ureg.Quantity(seconds_elapsed, ureg.second)
            additional_power = watthours - last_watthours
            power = additional_power / time_elapsed
            yield time, power.to(ureg.watt).magnitude
        last_watthours = watthours
        last_time = datapoint.collected_at
Example #5
0
 def value(self) -> t.Any:
     try:
         return ureg.Quantity(self.sensor.temperature, ureg.celsius)
     except DataCollectionError:
         # This is one of our own exceptions, we don't need to re-wrap it
         raise
     except (RuntimeError, AttributeError) as err:
         raise IntermittentSensorFailureError(
             "Couldn't determine temperature") from err
Example #6
0
    def value(self) -> t.Optional[t.Any]:
        try:
            import adafruit_dht
            import board

            sensor_type = getattr(adafruit_dht, self.board)
            pin = getattr(board, self.pin)
        except (ImportError, NotImplementedError, AttributeError):
            # No DHT library results in an ImportError.
            # Running on an unknown platform results in a
            # NotImplementedError when getting the pin
            return None
        try:
            return ureg.Quantity(sensor_type(pin).temperature, ureg.celsius)
        except RuntimeError:
            return None
Example #7
0
async def clean_watthours_to_watts(
    datapoints: t.AsyncIterator[DataPoint], ) -> CLEANED_DT_FLOAT:
    last_watthours = None
    last_time = None
    async for datapoint in datapoints:
        if datapoint.data is None:
            continue
        time = datapoint.collected_at
        if datapoint.data["unit"] == "watt_hour":
            watt_hours = datapoint.data["magnitude"]
        else:
            watt_hours = (ureg.Quantity(datapoint.data["magnitude"],
                                        datapoint.data["unit"]).to(
                                            ureg.watt_hour).magnitude)
        if last_watthours:
            seconds_elapsed = (time - last_time).total_seconds()
            hours_elapsed = seconds_elapsed / (60.0 * 60.0)
            additional_power = watt_hours - last_watthours
            power = additional_power / hours_elapsed
            yield time, power
        last_watthours = watt_hours
        last_time = datapoint.collected_at
def convert_temperature(magnitude: float, origin_unit: str,
                        target_unit: str) -> float:
    # if origin_unit == "degC" and target_unit == "degF":
    #    return (magnitude * 1.8) + 32
    temp = ureg.Quantity(magnitude, origin_unit)
    return temp.to(target_unit).magnitude
Example #9
0
 def from_json_compatible(cls, json_version: t.Any) -> t.Optional[t.Any]:
     if json_version:
         return ureg.Quantity(json_version["magnitude"],
                              ureg[json_version["unit"]])
     else:
         return None
Example #10
0
 def from_json_compatible(cls, json_version: t.Any) -> t.Any:
     return ureg.Quantity(json_version["magnitude"],
                          ureg[json_version["unit"]])
Example #11
0
 def value(self) -> t.Optional[t.Any]:
     try:
         return ureg.Quantity(self.sensor.temperature, ureg.celsius)
     except (RuntimeError, AttributeError):
         return None