sift_py.ingestion.channel

  1from __future__ import annotations
  2
  3from enum import Enum
  4from typing import List, Optional, Type, TypedDict, Union
  5
  6import sift.common.type.v1.channel_data_type_pb2 as channel_pb
  7from google.protobuf.empty_pb2 import Empty
  8from sift.channels.v3.channels_pb2 import Channel as ChannelPb
  9from sift.common.type.v1.channel_bit_field_element_pb2 import (
 10    ChannelBitFieldElement as ChannelBitFieldElementPb,
 11)
 12from sift.common.type.v1.channel_enum_type_pb2 import (
 13    ChannelEnumType as ChannelEnumTypePb,
 14)
 15from sift.ingest.v1.ingest_pb2 import IngestWithConfigDataChannelValue
 16from sift.ingestion_configs.v2.ingestion_configs_pb2 import ChannelConfig as ChannelConfigPb
 17from typing_extensions import NotRequired, Self
 18
 19from sift_py._internal.channel import channel_fqn as _channel_fqn
 20from sift_py._internal.convert.protobuf import AsProtobuf
 21from sift_py.error import _component_deprecation_warning
 22
 23
 24class ChannelValue(TypedDict):
 25    """
 26    Represents a fully qualified data point for a channel
 27    """
 28
 29    channel_name: str
 30    component: NotRequired[str]  # Deprecated
 31    value: IngestWithConfigDataChannelValue
 32
 33
 34class ChannelConfig(AsProtobuf):
 35    """
 36    A description for a channel
 37    """
 38
 39    name: str
 40    data_type: ChannelDataType
 41    description: Optional[str]
 42    unit: Optional[str]
 43    component: Optional[str]  # Deprecated
 44    bit_field_elements: List[ChannelBitFieldElement]
 45    enum_types: List[ChannelEnumType]
 46    identifier: str
 47
 48    def __init__(
 49        self,
 50        name: str,
 51        data_type: ChannelDataType,
 52        description: Optional[str] = None,
 53        unit: Optional[str] = None,
 54        component: Optional[str] = None,  # Deprecated
 55        bit_field_elements: List[ChannelBitFieldElement] = [],
 56        enum_types: List[ChannelEnumType] = [],
 57    ):
 58        self.name = name
 59        self.data_type = data_type
 60        self.description = description
 61        self.unit = unit
 62
 63        self.component = None  # Field kept for backwards compatibility
 64        if component:
 65            _component_deprecation_warning()
 66            self.name = _channel_fqn(name=self.name, component=component)
 67            self.component = None
 68
 69        self.bit_field_elements = bit_field_elements
 70        self.enum_types = enum_types
 71        self.identifier = self.fqn()
 72
 73    def value_from(
 74        self, value: Optional[Union[int, float, bool, str]]
 75    ) -> Optional[IngestWithConfigDataChannelValue]:
 76        """
 77        Like `try_value_from` except will return `None` there is a failure to produce a channel value due to a type mismatch.
 78        """
 79        try:
 80            return self.try_value_from(value)
 81        except ValueError:
 82            return None
 83
 84    def try_value_from(
 85        self, value: Optional[Union[int, float, bool, str]]
 86    ) -> IngestWithConfigDataChannelValue:
 87        """
 88        Generate a channel value for this particular channel configuration. This will raise an exception
 89        if there is a type match, namely, if `value` isn't consistent with the channel's data-type. For a version
 90        of this function that does not raise an exception and simply ignores type mistmatches, see `value_from`. If `value`
 91        is `None` then an empty value will be generated.
 92        """
 93        if value is None:
 94            return empty_value()
 95
 96        if isinstance(value, bool) and self.data_type == ChannelDataType.BOOL:
 97            return bool_value(value)
 98        elif isinstance(value, int) or isinstance(value, float):
 99            if self.data_type == ChannelDataType.INT_32:
100                return int32_value(int(value))
101            elif self.data_type == ChannelDataType.INT_64:
102                return int64_value(int(value))
103            elif self.data_type == ChannelDataType.UINT_32:
104                return uint32_value(int(value))
105            elif self.data_type == ChannelDataType.UINT_64:
106                return uint64_value(int(value))
107            elif self.data_type == ChannelDataType.FLOAT:
108                return float_value(float(value))
109            elif self.data_type == ChannelDataType.DOUBLE:
110                return double_value(float(value))
111            elif self.data_type == ChannelDataType.ENUM:
112                return enum_value(int(value))
113        elif isinstance(value, str) and self.data_type == ChannelDataType.STRING:
114            return string_value(value)
115
116        raise ValueError(f"Failed to cast value of type {type(value)} to {self.data_type}")
117
118    def as_pb(self, klass: Type[ChannelConfigPb]) -> ChannelConfigPb:
119        return klass(
120            name=self.name,
121            unit=self.unit or "",
122            description=self.description or "",
123            data_type=self.data_type.value,
124            enum_types=[etype.as_pb(ChannelEnumTypePb) for etype in self.enum_types],
125            bit_field_elements=[
126                el.as_pb(ChannelBitFieldElementPb) for el in self.bit_field_elements
127            ],
128        )
129
130    @classmethod
131    def from_pb(cls, message: ChannelConfigPb) -> Self:
132        return cls(
133            name=message.name,
134            data_type=ChannelDataType.from_pb(message.data_type),
135            description=message.description,
136            unit=message.unit,
137            bit_field_elements=[
138                ChannelBitFieldElement.from_pb(el) for el in message.bit_field_elements
139            ],
140            enum_types=[ChannelEnumType.from_pb(etype) for etype in message.enum_types],
141        )
142
143    def fqn(self) -> str:
144        """
145        NOTE: Component field of Channel has been deprecated. Function kept for backwards compatibility.
146
147        The fully-qualified channel name of a channel called 'voltage' is simply `voltage`. The
148        fully qualified name of a channel called 'temperature' of component 'motor' is a `motor.temperature'.
149        """
150        return channel_fqn(self)
151
152
153class ChannelBitFieldElement(AsProtobuf):
154    name: str
155    index: int
156    bit_count: int
157
158    def __init__(self, name: str, index: int, bit_count: int):
159        self.name = name
160        self.index = index
161        self.bit_count = bit_count
162
163    def as_pb(self, klass: Type[ChannelBitFieldElementPb]) -> ChannelBitFieldElementPb:
164        return klass(
165            name=self.name,
166            index=self.index,
167            bit_count=self.bit_count,
168        )
169
170    @classmethod
171    def from_pb(cls, message: ChannelBitFieldElementPb) -> Self:
172        return cls(
173            name=message.name,
174            index=message.index,
175            bit_count=message.bit_count,
176        )
177
178
179class ChannelEnumType(AsProtobuf):
180    name: str
181    key: int
182    is_signed: Optional[bool] = None
183
184    def __init__(self, name: str, key: int, is_signed: Optional[bool] = None):
185        self.name = name
186        self.key = key
187        self.is_signed = is_signed
188
189    def as_pb(self, klass: Type[ChannelEnumTypePb]) -> ChannelEnumTypePb:
190        return klass(
191            name=self.name,
192            key=self.key,
193            is_signed=False if self.is_signed is None else self.is_signed,
194        )
195
196    @classmethod
197    def from_pb(cls, message: ChannelEnumTypePb) -> Self:
198        return cls(name=message.name, key=message.key, is_signed=message.is_signed)
199
200
201class ChannelDataTypeStrRep(Enum):
202    DOUBLE = "double"
203    STRING = "string"
204    ENUM = "enum"
205    BIT_FIELD = "bit_field"
206    BOOL = "bool"
207    FLOAT = "float"
208    INT_32 = "int32"
209    INT_64 = "int64"
210    UINT_32 = "uint32"
211    UINT_64 = "uint64"
212
213    @staticmethod
214    def from_api_format(val: str) -> Optional["ChannelDataTypeStrRep"]:
215        try:
216            return {
217                "CHANNEL_DATA_TYPE_DOUBLE": ChannelDataTypeStrRep.DOUBLE,
218                "CHANNEL_DATA_TYPE_STRING": ChannelDataTypeStrRep.STRING,
219                "CHANNEL_DATA_TYPE_ENUM": ChannelDataTypeStrRep.ENUM,
220                "CHANNEL_DATA_TYPE_BIT_FIELD": ChannelDataTypeStrRep.BIT_FIELD,
221                "CHANNEL_DATA_TYPE_BOOL": ChannelDataTypeStrRep.BOOL,
222                "CHANNEL_DATA_TYPE_FLOAT": ChannelDataTypeStrRep.FLOAT,
223                "CHANNEL_DATA_TYPE_INT_32": ChannelDataTypeStrRep.INT_32,
224                "CHANNEL_DATA_TYPE_INT_64": ChannelDataTypeStrRep.INT_64,
225                "CHANNEL_DATA_TYPE_UINT_32": ChannelDataTypeStrRep.UINT_32,
226                "CHANNEL_DATA_TYPE_UINT_64": ChannelDataTypeStrRep.UINT_64,
227            }[val]
228        except KeyError:
229            return None
230
231
232class ChannelDataType(Enum):
233    """
234    Utility enum class to simplify working with channel data-types generated from protobuf
235    """
236
237    DOUBLE = channel_pb.CHANNEL_DATA_TYPE_DOUBLE
238    STRING = channel_pb.CHANNEL_DATA_TYPE_STRING
239    ENUM = channel_pb.CHANNEL_DATA_TYPE_ENUM
240    BIT_FIELD = channel_pb.CHANNEL_DATA_TYPE_BIT_FIELD
241    BOOL = channel_pb.CHANNEL_DATA_TYPE_BOOL
242    FLOAT = channel_pb.CHANNEL_DATA_TYPE_FLOAT
243    INT_32 = channel_pb.CHANNEL_DATA_TYPE_INT_32
244    INT_64 = channel_pb.CHANNEL_DATA_TYPE_INT_64
245    UINT_32 = channel_pb.CHANNEL_DATA_TYPE_UINT_32
246    UINT_64 = channel_pb.CHANNEL_DATA_TYPE_UINT_64
247
248    @classmethod
249    def from_pb(cls, val: channel_pb.ChannelDataType.ValueType) -> "ChannelDataType":
250        if val == cls.DOUBLE.value:
251            return cls.DOUBLE
252        elif val == cls.STRING.value:
253            return cls.STRING
254        elif val == cls.ENUM.value:
255            return cls.ENUM
256        elif val == cls.BIT_FIELD.value:
257            return cls.BIT_FIELD
258        elif val == cls.BOOL.value:
259            return cls.BOOL
260        elif val == cls.FLOAT.value:
261            return cls.FLOAT
262        elif val == cls.INT_32.value:
263            return cls.INT_32
264        elif val == cls.INT_64.value:
265            return cls.INT_64
266        elif val == cls.UINT_32.value:
267            return cls.UINT_32
268        elif val == cls.UINT_64.value:
269            return cls.UINT_64
270        else:
271            raise ValueError(f"Unknown channel data type '{val}'.")
272
273    @classmethod
274    def from_str(cls, raw: str) -> Optional["ChannelDataType"]:
275        if raw.startswith("CHANNEL_DATA_TYPE_"):
276            val = ChannelDataTypeStrRep.from_api_format(raw)
277            if val is None:
278                return None
279        else:
280            try:
281                val = ChannelDataTypeStrRep(raw)
282            except ValueError:
283                return None
284
285        if val == ChannelDataTypeStrRep.DOUBLE:
286            return cls.DOUBLE
287        elif val == ChannelDataTypeStrRep.STRING:
288            return cls.STRING
289        elif val == ChannelDataTypeStrRep.ENUM:
290            return cls.ENUM
291        elif val == ChannelDataTypeStrRep.BIT_FIELD:
292            return cls.BIT_FIELD
293        elif val == ChannelDataTypeStrRep.BOOL:
294            return cls.BOOL
295        elif val == ChannelDataTypeStrRep.FLOAT:
296            return cls.FLOAT
297        elif val == ChannelDataTypeStrRep.INT_32:
298            return cls.INT_32
299        elif val == ChannelDataTypeStrRep.INT_64:
300            return cls.INT_64
301        elif val == ChannelDataTypeStrRep.UINT_32:
302            return cls.UINT_32
303        elif val == ChannelDataTypeStrRep.UINT_64:
304            return cls.UINT_64
305        else:
306            raise Exception("Unreachable")
307
308    def as_human_str(self, api_format: bool = False) -> str:
309        if self == ChannelDataType.DOUBLE:
310            return "CHANNEL_DATA_TYPE_DOUBLE" if api_format else ChannelDataTypeStrRep.DOUBLE.value
311        elif self == ChannelDataType.STRING:
312            return "CHANNEL_DATA_TYPE_STRING" if api_format else ChannelDataTypeStrRep.STRING.value
313        elif self == ChannelDataType.ENUM:
314            return "CHANNEL_DATA_TYPE_ENUM" if api_format else ChannelDataTypeStrRep.ENUM.value
315        elif self == ChannelDataType.BIT_FIELD:
316            return (
317                "CHANNEL_DATA_TYPE_BIT_FIELD"
318                if api_format
319                else ChannelDataTypeStrRep.BIT_FIELD.value
320            )
321        elif self == ChannelDataType.BOOL:
322            return "CHANNEL_DATA_TYPE_BOOL" if api_format else ChannelDataTypeStrRep.BOOL.value
323        elif self == ChannelDataType.FLOAT:
324            return "CHANNEL_DATA_TYPE_FLOAT" if api_format else ChannelDataTypeStrRep.FLOAT.value
325        elif self == ChannelDataType.INT_32:
326            return "CHANNEL_DATA_TYPE_INT_32" if api_format else ChannelDataTypeStrRep.INT_32.value
327        elif self == ChannelDataType.INT_64:
328            return "CHANNEL_DATA_TYPE_INT_64" if api_format else ChannelDataTypeStrRep.INT_64.value
329        elif self == ChannelDataType.UINT_32:
330            return (
331                "CHANNEL_DATA_TYPE_UINT_32" if api_format else ChannelDataTypeStrRep.UINT_32.value
332            )
333        elif self == ChannelDataType.UINT_64:
334            return (
335                "CHANNEL_DATA_TYPE_UINT_64" if api_format else ChannelDataTypeStrRep.UINT_64.value
336            )
337        else:
338            raise Exception("Unreachable.")
339
340
341class _AbstractChannel(TypedDict):
342    channel_name: str
343    component: Optional[str]  # Deprecated
344
345
346def channel_fqn(
347    channel: Union[
348        ChannelConfig,
349        ChannelConfigPb,
350        ChannelValue,
351        ChannelPb,
352        _AbstractChannel,
353    ],
354) -> str:
355    """
356    Computes the fully qualified channel name.
357
358    NOTE: Component field of Channel is deprecated and should not be used. Function is left for code compatibility.
359
360    The fully-qualified channel name of a channel called 'voltage' is simply `voltage'. The
361    fully qualified name of a channel called 'temperature' of component 'motor' is a `motor.temperature'.
362    """
363
364    if isinstance(channel, ChannelConfig):
365        if channel.component:
366            _component_deprecation_warning()
367        return _channel_fqn(channel.name, channel.component)
368    elif isinstance(channel, ChannelConfigPb):
369        return channel.name
370    elif isinstance(channel, ChannelPb):
371        return channel.name
372    else:
373        component = channel.get("component")
374        if component:
375            _component_deprecation_warning()
376        channel_name = channel["channel_name"]
377        return _channel_fqn(name=channel_name, component=component)
378
379
380def string_value(val: str) -> IngestWithConfigDataChannelValue:
381    return IngestWithConfigDataChannelValue(string=val)
382
383
384def double_value(val: float) -> IngestWithConfigDataChannelValue:
385    return IngestWithConfigDataChannelValue(double=val)
386
387
388def float_value(val: float) -> IngestWithConfigDataChannelValue:
389    return IngestWithConfigDataChannelValue(float=val)
390
391
392def bool_value(val: bool) -> IngestWithConfigDataChannelValue:
393    return IngestWithConfigDataChannelValue(bool=val)
394
395
396def int32_value(val: int) -> IngestWithConfigDataChannelValue:
397    return IngestWithConfigDataChannelValue(int32=val)
398
399
400def uint32_value(val: int) -> IngestWithConfigDataChannelValue:
401    return IngestWithConfigDataChannelValue(uint32=val)
402
403
404def int64_value(val: int) -> IngestWithConfigDataChannelValue:
405    return IngestWithConfigDataChannelValue(int64=val)
406
407
408def uint64_value(val: int) -> IngestWithConfigDataChannelValue:
409    return IngestWithConfigDataChannelValue(uint64=val)
410
411
412def bit_field_value(val: bytes) -> IngestWithConfigDataChannelValue:
413    return IngestWithConfigDataChannelValue(bit_field=val)
414
415
416def enum_value(val: int) -> IngestWithConfigDataChannelValue:
417    return IngestWithConfigDataChannelValue(enum=val)
418
419
420def empty_value() -> IngestWithConfigDataChannelValue:
421    return IngestWithConfigDataChannelValue(empty=Empty())
422
423
424def is_data_type(val: IngestWithConfigDataChannelValue, target_type: ChannelDataType) -> bool:
425    if target_type == ChannelDataType.DOUBLE:
426        return val.HasField("double")
427    elif target_type == ChannelDataType.STRING:
428        return val.HasField("string")
429    elif target_type == ChannelDataType.ENUM:
430        return val.HasField("enum")
431    elif target_type == ChannelDataType.BIT_FIELD:
432        return val.HasField("bit_field")
433    elif target_type == ChannelDataType.BOOL:
434        return val.HasField("bool")
435    elif target_type == ChannelDataType.FLOAT:
436        return val.HasField("float")
437    elif target_type == ChannelDataType.INT_32:
438        return val.HasField("int32")
439    elif target_type == ChannelDataType.INT_64:
440        return val.HasField("int64")
441    elif target_type == ChannelDataType.UINT_32:
442        return val.HasField("uint32")
443    elif target_type == ChannelDataType.UINT_64:
444        return val.HasField("uint64")
class ChannelValue(builtins.dict):
25class ChannelValue(TypedDict):
26    """
27    Represents a fully qualified data point for a channel
28    """
29
30    channel_name: str
31    component: NotRequired[str]  # Deprecated
32    value: IngestWithConfigDataChannelValue

Represents a fully qualified data point for a channel

channel_name: str
component: typing_extensions.NotRequired[str]
value: sift.ingest.v1.ingest_pb2.IngestWithConfigDataChannelValue
Inherited Members
builtins.dict
get
setdefault
pop
popitem
keys
items
values
update
fromkeys
clear
copy
class ChannelConfig(abc.ABC, typing.Generic[~T]):
 35class ChannelConfig(AsProtobuf):
 36    """
 37    A description for a channel
 38    """
 39
 40    name: str
 41    data_type: ChannelDataType
 42    description: Optional[str]
 43    unit: Optional[str]
 44    component: Optional[str]  # Deprecated
 45    bit_field_elements: List[ChannelBitFieldElement]
 46    enum_types: List[ChannelEnumType]
 47    identifier: str
 48
 49    def __init__(
 50        self,
 51        name: str,
 52        data_type: ChannelDataType,
 53        description: Optional[str] = None,
 54        unit: Optional[str] = None,
 55        component: Optional[str] = None,  # Deprecated
 56        bit_field_elements: List[ChannelBitFieldElement] = [],
 57        enum_types: List[ChannelEnumType] = [],
 58    ):
 59        self.name = name
 60        self.data_type = data_type
 61        self.description = description
 62        self.unit = unit
 63
 64        self.component = None  # Field kept for backwards compatibility
 65        if component:
 66            _component_deprecation_warning()
 67            self.name = _channel_fqn(name=self.name, component=component)
 68            self.component = None
 69
 70        self.bit_field_elements = bit_field_elements
 71        self.enum_types = enum_types
 72        self.identifier = self.fqn()
 73
 74    def value_from(
 75        self, value: Optional[Union[int, float, bool, str]]
 76    ) -> Optional[IngestWithConfigDataChannelValue]:
 77        """
 78        Like `try_value_from` except will return `None` there is a failure to produce a channel value due to a type mismatch.
 79        """
 80        try:
 81            return self.try_value_from(value)
 82        except ValueError:
 83            return None
 84
 85    def try_value_from(
 86        self, value: Optional[Union[int, float, bool, str]]
 87    ) -> IngestWithConfigDataChannelValue:
 88        """
 89        Generate a channel value for this particular channel configuration. This will raise an exception
 90        if there is a type match, namely, if `value` isn't consistent with the channel's data-type. For a version
 91        of this function that does not raise an exception and simply ignores type mistmatches, see `value_from`. If `value`
 92        is `None` then an empty value will be generated.
 93        """
 94        if value is None:
 95            return empty_value()
 96
 97        if isinstance(value, bool) and self.data_type == ChannelDataType.BOOL:
 98            return bool_value(value)
 99        elif isinstance(value, int) or isinstance(value, float):
100            if self.data_type == ChannelDataType.INT_32:
101                return int32_value(int(value))
102            elif self.data_type == ChannelDataType.INT_64:
103                return int64_value(int(value))
104            elif self.data_type == ChannelDataType.UINT_32:
105                return uint32_value(int(value))
106            elif self.data_type == ChannelDataType.UINT_64:
107                return uint64_value(int(value))
108            elif self.data_type == ChannelDataType.FLOAT:
109                return float_value(float(value))
110            elif self.data_type == ChannelDataType.DOUBLE:
111                return double_value(float(value))
112            elif self.data_type == ChannelDataType.ENUM:
113                return enum_value(int(value))
114        elif isinstance(value, str) and self.data_type == ChannelDataType.STRING:
115            return string_value(value)
116
117        raise ValueError(f"Failed to cast value of type {type(value)} to {self.data_type}")
118
119    def as_pb(self, klass: Type[ChannelConfigPb]) -> ChannelConfigPb:
120        return klass(
121            name=self.name,
122            unit=self.unit or "",
123            description=self.description or "",
124            data_type=self.data_type.value,
125            enum_types=[etype.as_pb(ChannelEnumTypePb) for etype in self.enum_types],
126            bit_field_elements=[
127                el.as_pb(ChannelBitFieldElementPb) for el in self.bit_field_elements
128            ],
129        )
130
131    @classmethod
132    def from_pb(cls, message: ChannelConfigPb) -> Self:
133        return cls(
134            name=message.name,
135            data_type=ChannelDataType.from_pb(message.data_type),
136            description=message.description,
137            unit=message.unit,
138            bit_field_elements=[
139                ChannelBitFieldElement.from_pb(el) for el in message.bit_field_elements
140            ],
141            enum_types=[ChannelEnumType.from_pb(etype) for etype in message.enum_types],
142        )
143
144    def fqn(self) -> str:
145        """
146        NOTE: Component field of Channel has been deprecated. Function kept for backwards compatibility.
147
148        The fully-qualified channel name of a channel called 'voltage' is simply `voltage`. The
149        fully qualified name of a channel called 'temperature' of component 'motor' is a `motor.temperature'.
150        """
151        return channel_fqn(self)

A description for a channel

ChannelConfig( name: str, data_type: ChannelDataType, description: Union[str, NoneType] = None, unit: Union[str, NoneType] = None, component: Union[str, NoneType] = None, bit_field_elements: List[ChannelBitFieldElement] = [], enum_types: List[ChannelEnumType] = [])
49    def __init__(
50        self,
51        name: str,
52        data_type: ChannelDataType,
53        description: Optional[str] = None,
54        unit: Optional[str] = None,
55        component: Optional[str] = None,  # Deprecated
56        bit_field_elements: List[ChannelBitFieldElement] = [],
57        enum_types: List[ChannelEnumType] = [],
58    ):
59        self.name = name
60        self.data_type = data_type
61        self.description = description
62        self.unit = unit
63
64        self.component = None  # Field kept for backwards compatibility
65        if component:
66            _component_deprecation_warning()
67            self.name = _channel_fqn(name=self.name, component=component)
68            self.component = None
69
70        self.bit_field_elements = bit_field_elements
71        self.enum_types = enum_types
72        self.identifier = self.fqn()
name: str
data_type: ChannelDataType
description: Union[str, NoneType]
unit: Union[str, NoneType]
component: Union[str, NoneType]
bit_field_elements: List[ChannelBitFieldElement]
enum_types: List[ChannelEnumType]
identifier: str
def value_from( self, value: Union[int, float, bool, str, NoneType]) -> Union[sift.ingest.v1.ingest_pb2.IngestWithConfigDataChannelValue, NoneType]:
74    def value_from(
75        self, value: Optional[Union[int, float, bool, str]]
76    ) -> Optional[IngestWithConfigDataChannelValue]:
77        """
78        Like `try_value_from` except will return `None` there is a failure to produce a channel value due to a type mismatch.
79        """
80        try:
81            return self.try_value_from(value)
82        except ValueError:
83            return None

Like try_value_from except will return None there is a failure to produce a channel value due to a type mismatch.

def try_value_from( self, value: Union[int, float, bool, str, NoneType]) -> sift.ingest.v1.ingest_pb2.IngestWithConfigDataChannelValue:
 85    def try_value_from(
 86        self, value: Optional[Union[int, float, bool, str]]
 87    ) -> IngestWithConfigDataChannelValue:
 88        """
 89        Generate a channel value for this particular channel configuration. This will raise an exception
 90        if there is a type match, namely, if `value` isn't consistent with the channel's data-type. For a version
 91        of this function that does not raise an exception and simply ignores type mistmatches, see `value_from`. If `value`
 92        is `None` then an empty value will be generated.
 93        """
 94        if value is None:
 95            return empty_value()
 96
 97        if isinstance(value, bool) and self.data_type == ChannelDataType.BOOL:
 98            return bool_value(value)
 99        elif isinstance(value, int) or isinstance(value, float):
100            if self.data_type == ChannelDataType.INT_32:
101                return int32_value(int(value))
102            elif self.data_type == ChannelDataType.INT_64:
103                return int64_value(int(value))
104            elif self.data_type == ChannelDataType.UINT_32:
105                return uint32_value(int(value))
106            elif self.data_type == ChannelDataType.UINT_64:
107                return uint64_value(int(value))
108            elif self.data_type == ChannelDataType.FLOAT:
109                return float_value(float(value))
110            elif self.data_type == ChannelDataType.DOUBLE:
111                return double_value(float(value))
112            elif self.data_type == ChannelDataType.ENUM:
113                return enum_value(int(value))
114        elif isinstance(value, str) and self.data_type == ChannelDataType.STRING:
115            return string_value(value)
116
117        raise ValueError(f"Failed to cast value of type {type(value)} to {self.data_type}")

Generate a channel value for this particular channel configuration. This will raise an exception if there is a type match, namely, if value isn't consistent with the channel's data-type. For a version of this function that does not raise an exception and simply ignores type mistmatches, see value_from. If value is None then an empty value will be generated.

def as_pb( self, klass: Type[sift.ingestion_configs.v2.ingestion_configs_pb2.ChannelConfig]) -> sift.ingestion_configs.v2.ingestion_configs_pb2.ChannelConfig:
119    def as_pb(self, klass: Type[ChannelConfigPb]) -> ChannelConfigPb:
120        return klass(
121            name=self.name,
122            unit=self.unit or "",
123            description=self.description or "",
124            data_type=self.data_type.value,
125            enum_types=[etype.as_pb(ChannelEnumTypePb) for etype in self.enum_types],
126            bit_field_elements=[
127                el.as_pb(ChannelBitFieldElementPb) for el in self.bit_field_elements
128            ],
129        )

Performs the conversion into a sub-type of ProtobufMessage.

@classmethod
def from_pb( cls, message: sift.ingestion_configs.v2.ingestion_configs_pb2.ChannelConfig) -> typing_extensions.Self:
131    @classmethod
132    def from_pb(cls, message: ChannelConfigPb) -> Self:
133        return cls(
134            name=message.name,
135            data_type=ChannelDataType.from_pb(message.data_type),
136            description=message.description,
137            unit=message.unit,
138            bit_field_elements=[
139                ChannelBitFieldElement.from_pb(el) for el in message.bit_field_elements
140            ],
141            enum_types=[ChannelEnumType.from_pb(etype) for etype in message.enum_types],
142        )

Converts a protobuf object to the type of the sub-class class.

def fqn(self) -> str:
144    def fqn(self) -> str:
145        """
146        NOTE: Component field of Channel has been deprecated. Function kept for backwards compatibility.
147
148        The fully-qualified channel name of a channel called 'voltage' is simply `voltage`. The
149        fully qualified name of a channel called 'temperature' of component 'motor' is a `motor.temperature'.
150        """
151        return channel_fqn(self)

NOTE: Component field of Channel has been deprecated. Function kept for backwards compatibility.

The fully-qualified channel name of a channel called 'voltage' is simply voltage. The fully qualified name of a channel called 'temperature' of component 'motor' is a `motor.temperature'.

class ChannelBitFieldElement(abc.ABC, typing.Generic[~T]):
154class ChannelBitFieldElement(AsProtobuf):
155    name: str
156    index: int
157    bit_count: int
158
159    def __init__(self, name: str, index: int, bit_count: int):
160        self.name = name
161        self.index = index
162        self.bit_count = bit_count
163
164    def as_pb(self, klass: Type[ChannelBitFieldElementPb]) -> ChannelBitFieldElementPb:
165        return klass(
166            name=self.name,
167            index=self.index,
168            bit_count=self.bit_count,
169        )
170
171    @classmethod
172    def from_pb(cls, message: ChannelBitFieldElementPb) -> Self:
173        return cls(
174            name=message.name,
175            index=message.index,
176            bit_count=message.bit_count,
177        )

Abstract base class used to create create sub-types that can be treated as an object that can be converted into an instance of ProtobufMessage.

If there are multiple possible protobuf targets then as_pb may be overloaded.

ChannelBitFieldElement(name: str, index: int, bit_count: int)
159    def __init__(self, name: str, index: int, bit_count: int):
160        self.name = name
161        self.index = index
162        self.bit_count = bit_count
name: str
index: int
bit_count: int
def as_pb( self, klass: Type[sift.common.type.v1.channel_bit_field_element_pb2.ChannelBitFieldElement]) -> sift.common.type.v1.channel_bit_field_element_pb2.ChannelBitFieldElement:
164    def as_pb(self, klass: Type[ChannelBitFieldElementPb]) -> ChannelBitFieldElementPb:
165        return klass(
166            name=self.name,
167            index=self.index,
168            bit_count=self.bit_count,
169        )

Performs the conversion into a sub-type of ProtobufMessage.

@classmethod
def from_pb( cls, message: sift.common.type.v1.channel_bit_field_element_pb2.ChannelBitFieldElement) -> typing_extensions.Self:
171    @classmethod
172    def from_pb(cls, message: ChannelBitFieldElementPb) -> Self:
173        return cls(
174            name=message.name,
175            index=message.index,
176            bit_count=message.bit_count,
177        )

Converts a protobuf object to the type of the sub-class class.

class ChannelEnumType(abc.ABC, typing.Generic[~T]):
180class ChannelEnumType(AsProtobuf):
181    name: str
182    key: int
183    is_signed: Optional[bool] = None
184
185    def __init__(self, name: str, key: int, is_signed: Optional[bool] = None):
186        self.name = name
187        self.key = key
188        self.is_signed = is_signed
189
190    def as_pb(self, klass: Type[ChannelEnumTypePb]) -> ChannelEnumTypePb:
191        return klass(
192            name=self.name,
193            key=self.key,
194            is_signed=False if self.is_signed is None else self.is_signed,
195        )
196
197    @classmethod
198    def from_pb(cls, message: ChannelEnumTypePb) -> Self:
199        return cls(name=message.name, key=message.key, is_signed=message.is_signed)

Abstract base class used to create create sub-types that can be treated as an object that can be converted into an instance of ProtobufMessage.

If there are multiple possible protobuf targets then as_pb may be overloaded.

ChannelEnumType(name: str, key: int, is_signed: Union[bool, NoneType] = None)
185    def __init__(self, name: str, key: int, is_signed: Optional[bool] = None):
186        self.name = name
187        self.key = key
188        self.is_signed = is_signed
name: str
key: int
is_signed: Union[bool, NoneType] = None
def as_pb( self, klass: Type[sift.common.type.v1.channel_enum_type_pb2.ChannelEnumType]) -> sift.common.type.v1.channel_enum_type_pb2.ChannelEnumType:
190    def as_pb(self, klass: Type[ChannelEnumTypePb]) -> ChannelEnumTypePb:
191        return klass(
192            name=self.name,
193            key=self.key,
194            is_signed=False if self.is_signed is None else self.is_signed,
195        )

Performs the conversion into a sub-type of ProtobufMessage.

@classmethod
def from_pb( cls, message: sift.common.type.v1.channel_enum_type_pb2.ChannelEnumType) -> typing_extensions.Self:
197    @classmethod
198    def from_pb(cls, message: ChannelEnumTypePb) -> Self:
199        return cls(name=message.name, key=message.key, is_signed=message.is_signed)

Converts a protobuf object to the type of the sub-class class.

class ChannelDataTypeStrRep(enum.Enum):
202class ChannelDataTypeStrRep(Enum):
203    DOUBLE = "double"
204    STRING = "string"
205    ENUM = "enum"
206    BIT_FIELD = "bit_field"
207    BOOL = "bool"
208    FLOAT = "float"
209    INT_32 = "int32"
210    INT_64 = "int64"
211    UINT_32 = "uint32"
212    UINT_64 = "uint64"
213
214    @staticmethod
215    def from_api_format(val: str) -> Optional["ChannelDataTypeStrRep"]:
216        try:
217            return {
218                "CHANNEL_DATA_TYPE_DOUBLE": ChannelDataTypeStrRep.DOUBLE,
219                "CHANNEL_DATA_TYPE_STRING": ChannelDataTypeStrRep.STRING,
220                "CHANNEL_DATA_TYPE_ENUM": ChannelDataTypeStrRep.ENUM,
221                "CHANNEL_DATA_TYPE_BIT_FIELD": ChannelDataTypeStrRep.BIT_FIELD,
222                "CHANNEL_DATA_TYPE_BOOL": ChannelDataTypeStrRep.BOOL,
223                "CHANNEL_DATA_TYPE_FLOAT": ChannelDataTypeStrRep.FLOAT,
224                "CHANNEL_DATA_TYPE_INT_32": ChannelDataTypeStrRep.INT_32,
225                "CHANNEL_DATA_TYPE_INT_64": ChannelDataTypeStrRep.INT_64,
226                "CHANNEL_DATA_TYPE_UINT_32": ChannelDataTypeStrRep.UINT_32,
227                "CHANNEL_DATA_TYPE_UINT_64": ChannelDataTypeStrRep.UINT_64,
228            }[val]
229        except KeyError:
230            return None

An enumeration.

DOUBLE = <ChannelDataTypeStrRep.DOUBLE: 'double'>
STRING = <ChannelDataTypeStrRep.STRING: 'string'>
ENUM = <ChannelDataTypeStrRep.ENUM: 'enum'>
BIT_FIELD = <ChannelDataTypeStrRep.BIT_FIELD: 'bit_field'>
BOOL = <ChannelDataTypeStrRep.BOOL: 'bool'>
FLOAT = <ChannelDataTypeStrRep.FLOAT: 'float'>
INT_32 = <ChannelDataTypeStrRep.INT_32: 'int32'>
INT_64 = <ChannelDataTypeStrRep.INT_64: 'int64'>
UINT_32 = <ChannelDataTypeStrRep.UINT_32: 'uint32'>
UINT_64 = <ChannelDataTypeStrRep.UINT_64: 'uint64'>
@staticmethod
def from_api_format( val: str) -> Union[ChannelDataTypeStrRep, NoneType]:
214    @staticmethod
215    def from_api_format(val: str) -> Optional["ChannelDataTypeStrRep"]:
216        try:
217            return {
218                "CHANNEL_DATA_TYPE_DOUBLE": ChannelDataTypeStrRep.DOUBLE,
219                "CHANNEL_DATA_TYPE_STRING": ChannelDataTypeStrRep.STRING,
220                "CHANNEL_DATA_TYPE_ENUM": ChannelDataTypeStrRep.ENUM,
221                "CHANNEL_DATA_TYPE_BIT_FIELD": ChannelDataTypeStrRep.BIT_FIELD,
222                "CHANNEL_DATA_TYPE_BOOL": ChannelDataTypeStrRep.BOOL,
223                "CHANNEL_DATA_TYPE_FLOAT": ChannelDataTypeStrRep.FLOAT,
224                "CHANNEL_DATA_TYPE_INT_32": ChannelDataTypeStrRep.INT_32,
225                "CHANNEL_DATA_TYPE_INT_64": ChannelDataTypeStrRep.INT_64,
226                "CHANNEL_DATA_TYPE_UINT_32": ChannelDataTypeStrRep.UINT_32,
227                "CHANNEL_DATA_TYPE_UINT_64": ChannelDataTypeStrRep.UINT_64,
228            }[val]
229        except KeyError:
230            return None
Inherited Members
enum.Enum
name
value
class ChannelDataType(enum.Enum):
233class ChannelDataType(Enum):
234    """
235    Utility enum class to simplify working with channel data-types generated from protobuf
236    """
237
238    DOUBLE = channel_pb.CHANNEL_DATA_TYPE_DOUBLE
239    STRING = channel_pb.CHANNEL_DATA_TYPE_STRING
240    ENUM = channel_pb.CHANNEL_DATA_TYPE_ENUM
241    BIT_FIELD = channel_pb.CHANNEL_DATA_TYPE_BIT_FIELD
242    BOOL = channel_pb.CHANNEL_DATA_TYPE_BOOL
243    FLOAT = channel_pb.CHANNEL_DATA_TYPE_FLOAT
244    INT_32 = channel_pb.CHANNEL_DATA_TYPE_INT_32
245    INT_64 = channel_pb.CHANNEL_DATA_TYPE_INT_64
246    UINT_32 = channel_pb.CHANNEL_DATA_TYPE_UINT_32
247    UINT_64 = channel_pb.CHANNEL_DATA_TYPE_UINT_64
248
249    @classmethod
250    def from_pb(cls, val: channel_pb.ChannelDataType.ValueType) -> "ChannelDataType":
251        if val == cls.DOUBLE.value:
252            return cls.DOUBLE
253        elif val == cls.STRING.value:
254            return cls.STRING
255        elif val == cls.ENUM.value:
256            return cls.ENUM
257        elif val == cls.BIT_FIELD.value:
258            return cls.BIT_FIELD
259        elif val == cls.BOOL.value:
260            return cls.BOOL
261        elif val == cls.FLOAT.value:
262            return cls.FLOAT
263        elif val == cls.INT_32.value:
264            return cls.INT_32
265        elif val == cls.INT_64.value:
266            return cls.INT_64
267        elif val == cls.UINT_32.value:
268            return cls.UINT_32
269        elif val == cls.UINT_64.value:
270            return cls.UINT_64
271        else:
272            raise ValueError(f"Unknown channel data type '{val}'.")
273
274    @classmethod
275    def from_str(cls, raw: str) -> Optional["ChannelDataType"]:
276        if raw.startswith("CHANNEL_DATA_TYPE_"):
277            val = ChannelDataTypeStrRep.from_api_format(raw)
278            if val is None:
279                return None
280        else:
281            try:
282                val = ChannelDataTypeStrRep(raw)
283            except ValueError:
284                return None
285
286        if val == ChannelDataTypeStrRep.DOUBLE:
287            return cls.DOUBLE
288        elif val == ChannelDataTypeStrRep.STRING:
289            return cls.STRING
290        elif val == ChannelDataTypeStrRep.ENUM:
291            return cls.ENUM
292        elif val == ChannelDataTypeStrRep.BIT_FIELD:
293            return cls.BIT_FIELD
294        elif val == ChannelDataTypeStrRep.BOOL:
295            return cls.BOOL
296        elif val == ChannelDataTypeStrRep.FLOAT:
297            return cls.FLOAT
298        elif val == ChannelDataTypeStrRep.INT_32:
299            return cls.INT_32
300        elif val == ChannelDataTypeStrRep.INT_64:
301            return cls.INT_64
302        elif val == ChannelDataTypeStrRep.UINT_32:
303            return cls.UINT_32
304        elif val == ChannelDataTypeStrRep.UINT_64:
305            return cls.UINT_64
306        else:
307            raise Exception("Unreachable")
308
309    def as_human_str(self, api_format: bool = False) -> str:
310        if self == ChannelDataType.DOUBLE:
311            return "CHANNEL_DATA_TYPE_DOUBLE" if api_format else ChannelDataTypeStrRep.DOUBLE.value
312        elif self == ChannelDataType.STRING:
313            return "CHANNEL_DATA_TYPE_STRING" if api_format else ChannelDataTypeStrRep.STRING.value
314        elif self == ChannelDataType.ENUM:
315            return "CHANNEL_DATA_TYPE_ENUM" if api_format else ChannelDataTypeStrRep.ENUM.value
316        elif self == ChannelDataType.BIT_FIELD:
317            return (
318                "CHANNEL_DATA_TYPE_BIT_FIELD"
319                if api_format
320                else ChannelDataTypeStrRep.BIT_FIELD.value
321            )
322        elif self == ChannelDataType.BOOL:
323            return "CHANNEL_DATA_TYPE_BOOL" if api_format else ChannelDataTypeStrRep.BOOL.value
324        elif self == ChannelDataType.FLOAT:
325            return "CHANNEL_DATA_TYPE_FLOAT" if api_format else ChannelDataTypeStrRep.FLOAT.value
326        elif self == ChannelDataType.INT_32:
327            return "CHANNEL_DATA_TYPE_INT_32" if api_format else ChannelDataTypeStrRep.INT_32.value
328        elif self == ChannelDataType.INT_64:
329            return "CHANNEL_DATA_TYPE_INT_64" if api_format else ChannelDataTypeStrRep.INT_64.value
330        elif self == ChannelDataType.UINT_32:
331            return (
332                "CHANNEL_DATA_TYPE_UINT_32" if api_format else ChannelDataTypeStrRep.UINT_32.value
333            )
334        elif self == ChannelDataType.UINT_64:
335            return (
336                "CHANNEL_DATA_TYPE_UINT_64" if api_format else ChannelDataTypeStrRep.UINT_64.value
337            )
338        else:
339            raise Exception("Unreachable.")

Utility enum class to simplify working with channel data-types generated from protobuf

DOUBLE = <ChannelDataType.DOUBLE: 1>
STRING = <ChannelDataType.STRING: 2>
ENUM = <ChannelDataType.ENUM: 3>
BIT_FIELD = <ChannelDataType.BIT_FIELD: 4>
BOOL = <ChannelDataType.BOOL: 5>
FLOAT = <ChannelDataType.FLOAT: 6>
INT_32 = <ChannelDataType.INT_32: 7>
INT_64 = <ChannelDataType.INT_64: 9>
UINT_32 = <ChannelDataType.UINT_32: 8>
UINT_64 = <ChannelDataType.UINT_64: 10>
@classmethod
def from_pb(cls, val: int) -> ChannelDataType:
249    @classmethod
250    def from_pb(cls, val: channel_pb.ChannelDataType.ValueType) -> "ChannelDataType":
251        if val == cls.DOUBLE.value:
252            return cls.DOUBLE
253        elif val == cls.STRING.value:
254            return cls.STRING
255        elif val == cls.ENUM.value:
256            return cls.ENUM
257        elif val == cls.BIT_FIELD.value:
258            return cls.BIT_FIELD
259        elif val == cls.BOOL.value:
260            return cls.BOOL
261        elif val == cls.FLOAT.value:
262            return cls.FLOAT
263        elif val == cls.INT_32.value:
264            return cls.INT_32
265        elif val == cls.INT_64.value:
266            return cls.INT_64
267        elif val == cls.UINT_32.value:
268            return cls.UINT_32
269        elif val == cls.UINT_64.value:
270            return cls.UINT_64
271        else:
272            raise ValueError(f"Unknown channel data type '{val}'.")
@classmethod
def from_str( cls, raw: str) -> Union[ChannelDataType, NoneType]:
274    @classmethod
275    def from_str(cls, raw: str) -> Optional["ChannelDataType"]:
276        if raw.startswith("CHANNEL_DATA_TYPE_"):
277            val = ChannelDataTypeStrRep.from_api_format(raw)
278            if val is None:
279                return None
280        else:
281            try:
282                val = ChannelDataTypeStrRep(raw)
283            except ValueError:
284                return None
285
286        if val == ChannelDataTypeStrRep.DOUBLE:
287            return cls.DOUBLE
288        elif val == ChannelDataTypeStrRep.STRING:
289            return cls.STRING
290        elif val == ChannelDataTypeStrRep.ENUM:
291            return cls.ENUM
292        elif val == ChannelDataTypeStrRep.BIT_FIELD:
293            return cls.BIT_FIELD
294        elif val == ChannelDataTypeStrRep.BOOL:
295            return cls.BOOL
296        elif val == ChannelDataTypeStrRep.FLOAT:
297            return cls.FLOAT
298        elif val == ChannelDataTypeStrRep.INT_32:
299            return cls.INT_32
300        elif val == ChannelDataTypeStrRep.INT_64:
301            return cls.INT_64
302        elif val == ChannelDataTypeStrRep.UINT_32:
303            return cls.UINT_32
304        elif val == ChannelDataTypeStrRep.UINT_64:
305            return cls.UINT_64
306        else:
307            raise Exception("Unreachable")
def as_human_str(self, api_format: bool = False) -> str:
309    def as_human_str(self, api_format: bool = False) -> str:
310        if self == ChannelDataType.DOUBLE:
311            return "CHANNEL_DATA_TYPE_DOUBLE" if api_format else ChannelDataTypeStrRep.DOUBLE.value
312        elif self == ChannelDataType.STRING:
313            return "CHANNEL_DATA_TYPE_STRING" if api_format else ChannelDataTypeStrRep.STRING.value
314        elif self == ChannelDataType.ENUM:
315            return "CHANNEL_DATA_TYPE_ENUM" if api_format else ChannelDataTypeStrRep.ENUM.value
316        elif self == ChannelDataType.BIT_FIELD:
317            return (
318                "CHANNEL_DATA_TYPE_BIT_FIELD"
319                if api_format
320                else ChannelDataTypeStrRep.BIT_FIELD.value
321            )
322        elif self == ChannelDataType.BOOL:
323            return "CHANNEL_DATA_TYPE_BOOL" if api_format else ChannelDataTypeStrRep.BOOL.value
324        elif self == ChannelDataType.FLOAT:
325            return "CHANNEL_DATA_TYPE_FLOAT" if api_format else ChannelDataTypeStrRep.FLOAT.value
326        elif self == ChannelDataType.INT_32:
327            return "CHANNEL_DATA_TYPE_INT_32" if api_format else ChannelDataTypeStrRep.INT_32.value
328        elif self == ChannelDataType.INT_64:
329            return "CHANNEL_DATA_TYPE_INT_64" if api_format else ChannelDataTypeStrRep.INT_64.value
330        elif self == ChannelDataType.UINT_32:
331            return (
332                "CHANNEL_DATA_TYPE_UINT_32" if api_format else ChannelDataTypeStrRep.UINT_32.value
333            )
334        elif self == ChannelDataType.UINT_64:
335            return (
336                "CHANNEL_DATA_TYPE_UINT_64" if api_format else ChannelDataTypeStrRep.UINT_64.value
337            )
338        else:
339            raise Exception("Unreachable.")
Inherited Members
enum.Enum
name
value
def channel_fqn( channel: Union[ChannelConfig, sift.ingestion_configs.v2.ingestion_configs_pb2.ChannelConfig, ChannelValue, sift.channels.v3.channels_pb2.Channel, sift_py.ingestion.channel._AbstractChannel]) -> str:
347def channel_fqn(
348    channel: Union[
349        ChannelConfig,
350        ChannelConfigPb,
351        ChannelValue,
352        ChannelPb,
353        _AbstractChannel,
354    ],
355) -> str:
356    """
357    Computes the fully qualified channel name.
358
359    NOTE: Component field of Channel is deprecated and should not be used. Function is left for code compatibility.
360
361    The fully-qualified channel name of a channel called 'voltage' is simply `voltage'. The
362    fully qualified name of a channel called 'temperature' of component 'motor' is a `motor.temperature'.
363    """
364
365    if isinstance(channel, ChannelConfig):
366        if channel.component:
367            _component_deprecation_warning()
368        return _channel_fqn(channel.name, channel.component)
369    elif isinstance(channel, ChannelConfigPb):
370        return channel.name
371    elif isinstance(channel, ChannelPb):
372        return channel.name
373    else:
374        component = channel.get("component")
375        if component:
376            _component_deprecation_warning()
377        channel_name = channel["channel_name"]
378        return _channel_fqn(name=channel_name, component=component)

Computes the fully qualified channel name.

NOTE: Component field of Channel is deprecated and should not be used. Function is left for code compatibility.

The fully-qualified channel name of a channel called 'voltage' is simply voltage'. The fully qualified name of a channel called 'temperature' of component 'motor' is amotor.temperature'.

def string_value(val: str) -> sift.ingest.v1.ingest_pb2.IngestWithConfigDataChannelValue:
381def string_value(val: str) -> IngestWithConfigDataChannelValue:
382    return IngestWithConfigDataChannelValue(string=val)
def double_value(val: float) -> sift.ingest.v1.ingest_pb2.IngestWithConfigDataChannelValue:
385def double_value(val: float) -> IngestWithConfigDataChannelValue:
386    return IngestWithConfigDataChannelValue(double=val)
def float_value(val: float) -> sift.ingest.v1.ingest_pb2.IngestWithConfigDataChannelValue:
389def float_value(val: float) -> IngestWithConfigDataChannelValue:
390    return IngestWithConfigDataChannelValue(float=val)
def bool_value(val: bool) -> sift.ingest.v1.ingest_pb2.IngestWithConfigDataChannelValue:
393def bool_value(val: bool) -> IngestWithConfigDataChannelValue:
394    return IngestWithConfigDataChannelValue(bool=val)
def int32_value(val: int) -> sift.ingest.v1.ingest_pb2.IngestWithConfigDataChannelValue:
397def int32_value(val: int) -> IngestWithConfigDataChannelValue:
398    return IngestWithConfigDataChannelValue(int32=val)
def uint32_value(val: int) -> sift.ingest.v1.ingest_pb2.IngestWithConfigDataChannelValue:
401def uint32_value(val: int) -> IngestWithConfigDataChannelValue:
402    return IngestWithConfigDataChannelValue(uint32=val)
def int64_value(val: int) -> sift.ingest.v1.ingest_pb2.IngestWithConfigDataChannelValue:
405def int64_value(val: int) -> IngestWithConfigDataChannelValue:
406    return IngestWithConfigDataChannelValue(int64=val)
def uint64_value(val: int) -> sift.ingest.v1.ingest_pb2.IngestWithConfigDataChannelValue:
409def uint64_value(val: int) -> IngestWithConfigDataChannelValue:
410    return IngestWithConfigDataChannelValue(uint64=val)
def bit_field_value(val: bytes) -> sift.ingest.v1.ingest_pb2.IngestWithConfigDataChannelValue:
413def bit_field_value(val: bytes) -> IngestWithConfigDataChannelValue:
414    return IngestWithConfigDataChannelValue(bit_field=val)
def enum_value(val: int) -> sift.ingest.v1.ingest_pb2.IngestWithConfigDataChannelValue:
417def enum_value(val: int) -> IngestWithConfigDataChannelValue:
418    return IngestWithConfigDataChannelValue(enum=val)
def empty_value() -> sift.ingest.v1.ingest_pb2.IngestWithConfigDataChannelValue:
421def empty_value() -> IngestWithConfigDataChannelValue:
422    return IngestWithConfigDataChannelValue(empty=Empty())
def is_data_type( val: sift.ingest.v1.ingest_pb2.IngestWithConfigDataChannelValue, target_type: ChannelDataType) -> bool:
425def is_data_type(val: IngestWithConfigDataChannelValue, target_type: ChannelDataType) -> bool:
426    if target_type == ChannelDataType.DOUBLE:
427        return val.HasField("double")
428    elif target_type == ChannelDataType.STRING:
429        return val.HasField("string")
430    elif target_type == ChannelDataType.ENUM:
431        return val.HasField("enum")
432    elif target_type == ChannelDataType.BIT_FIELD:
433        return val.HasField("bit_field")
434    elif target_type == ChannelDataType.BOOL:
435        return val.HasField("bool")
436    elif target_type == ChannelDataType.FLOAT:
437        return val.HasField("float")
438    elif target_type == ChannelDataType.INT_32:
439        return val.HasField("int32")
440    elif target_type == ChannelDataType.INT_64:
441        return val.HasField("int64")
442    elif target_type == ChannelDataType.UINT_32:
443        return val.HasField("uint32")
444    elif target_type == ChannelDataType.UINT_64:
445        return val.HasField("uint64")