diff --git a/docs/source/Resources/Devices/Devices_Type.rst b/docs/source/Resources/Devices/Devices_Type.rst index 2b2f5d8..be245e5 100644 --- a/docs/source/Resources/Devices/Devices_Type.rst +++ b/docs/source/Resources/Devices/Devices_Type.rst @@ -265,9 +265,9 @@ DeviceCreateInfoBasicMutable -.. _DeviceCreateInfoBasicImutable: +.. _DeviceCreateInfoBasicImmutable: -DeviceCreateInfoBasicImutable +DeviceCreateInfoBasicImmutable -------------------------------- **Attributes:** @@ -281,7 +281,7 @@ DeviceCreateInfoBasicImutable | **network**: :ref:`GenericID` | Network ID. - | **type**: "imutable" + | **type**: "immutable" | Device's data storage (bucket) type. | :default: "legacy" @@ -332,7 +332,7 @@ DeviceCreateInfoMutable DeviceCreateInfoImmutable -------------------------- - **DeviceCreateInfoImmutable** = DeviceCreateInfoBasicImutable + **DeviceCreateInfoImmutable** = DeviceCreateInfoBasicImmutable .. _DeviceCreateInfo: diff --git a/src/tagoio_sdk/modules/Resources/Buckets_Type.py b/src/tagoio_sdk/modules/Resources/Buckets_Type.py index 9386f36..f93f9e8 100644 --- a/src/tagoio_sdk/modules/Resources/Buckets_Type.py +++ b/src/tagoio_sdk/modules/Resources/Buckets_Type.py @@ -8,7 +8,7 @@ from tagoio_sdk.common.Common_Type import TagsObj -DataStorageType = Literal["immutable", "mutable", "legacy"] +DataStorageType = Literal["immutable", "mutable", "legacy", "hybrid"] class ExportBucketOption(TypedDict): diff --git a/src/tagoio_sdk/modules/Resources/Device_Type.py b/src/tagoio_sdk/modules/Resources/Device_Type.py index 6b87af0..5a96e9c 100644 --- a/src/tagoio_sdk/modules/Resources/Device_Type.py +++ b/src/tagoio_sdk/modules/Resources/Device_Type.py @@ -58,6 +58,14 @@ class DeviceInfo(TypedDict): """ Date for the device's last data retention. """ + mutable_variable_regex: str or None + """ + Regex that routes each variable to the mutable side at insert time (unanchored substring match). + + It must not match every variable or no variable; use a mutable or immutable device for those cases. + + Present for Hybrid devices. Can only be changed while the device is empty. + """ class DeviceInfoList(TypedDict): @@ -270,7 +278,74 @@ class DeviceCreateInfoBasicMutable(TypedDict): """ -class DeviceCreateInfoBasicImutable(TypedDict): +class DeviceCreateInfoBasicImmutable(TypedDict): + name: str + """ + Device name. + """ + connector: GenericID + """ + Connector ID. + """ + network: GenericID + """ + Network ID. + """ + type: Literal["immutable"] + """ + Device's data storage (bucket) type. + + :default: "legacy" + """ + description: str or None + """ + Description of the device. + """ + active: bool + """ + Set if the device will be active. + """ + visible: bool + """ + Set if the device will be visible. + """ + configuration_params: list[ConfigurationParams] + """ + An array of configuration params + """ + tags: list[TagsObj] + """ + An array of tags + """ + serie_number: str + """ + Device serial number. + """ + connector_parse: bool + """ + If device will use connector parser + """ + parse_function: str + """ + Javascript code for use as payload parser + """ + chunk_period: Literal["day", "week", "month", "quarter"] + """ + Chunk division to retain data in the device. + + Required for Immutable devices. + """ + chunk_retention: Union[int, float] + """ + Amount of chunks to retain data according to the `chunk_period`. + + Integer between in the range of 0 to 36 (inclusive). + + Required for Immutable devices. + """ + + +class DeviceCreateInfoBasicHybrid(TypedDict): name: str """ Device name. @@ -283,7 +358,7 @@ class DeviceCreateInfoBasicImutable(TypedDict): """ Network ID. """ - type: Literal["imutable"] + type: Literal["hybrid"] """ Device's data storage (bucket) type. @@ -335,13 +410,25 @@ class DeviceCreateInfoBasicImutable(TypedDict): Required for Immutable devices. """ + mutable_variable_regex: str + """ + Regex that routes each variable to the mutable side at insert time (unanchored substring match). + + It must not match every variable or no variable; use a mutable or immutable device for those cases. + + Required for Hybrid devices. Can only be changed while the device is empty. + """ DeviceCreateInfoMutable = DeviceCreateInfoBasicMutable -DeviceCreateInfoImmutable = DeviceCreateInfoBasicImutable +DeviceCreateInfoImmutable = DeviceCreateInfoBasicImmutable + +DeviceCreateInfoHybrid = DeviceCreateInfoBasicHybrid -DeviceCreateInfo = DeviceCreateInfoMutable or DeviceCreateInfoImmutable +DeviceCreateInfo = ( + DeviceCreateInfoMutable or DeviceCreateInfoImmutable or DeviceCreateInfoHybrid +) class DeviceEditInfo(TypedDict): @@ -397,11 +484,28 @@ class DeviceEditInfo(TypedDict): Required for Immutable devices. """ + mutable_variable_regex: Optional[str] + """ + Regex that routes each variable to the mutable side at insert time (unanchored substring match). + + It must not match every variable or no variable; use a mutable or immutable device for those cases. + + Required for Hybrid devices. Can only be changed while the device is empty. + """ DeviceEditInfo = DeviceEditInfo +class DeviceEmptyParams(TypedDict, total=False): + route: Literal["mutable", "immutable"] + """ + For Hybrid devices only: empty a single side of the device instead of everything. + "mutable" truncates the editable variables; "immutable" drops the telemetry chunks. + Omit to remove all data (every device type). + """ + + class TokenData(TypedDict): name: str """ diff --git a/src/tagoio_sdk/modules/Resources/Devices.py b/src/tagoio_sdk/modules/Resources/Devices.py index 7292ca3..f924b7b 100644 --- a/src/tagoio_sdk/modules/Resources/Devices.py +++ b/src/tagoio_sdk/modules/Resources/Devices.py @@ -19,6 +19,7 @@ from tagoio_sdk.modules.Resources.Device_Type import DeviceDataBackupResponse from tagoio_sdk.modules.Resources.Device_Type import DeviceDataRestore from tagoio_sdk.modules.Resources.Device_Type import DeviceEditInfo +from tagoio_sdk.modules.Resources.Device_Type import DeviceEmptyParams from tagoio_sdk.modules.Resources.Device_Type import DeviceListItem from tagoio_sdk.modules.Resources.Device_Type import DeviceQuery from tagoio_sdk.modules.Resources.Device_Type import DeviceTokenDataList @@ -451,10 +452,12 @@ def getDeviceData(self, deviceID: GenericID, queryParams: DataQuery = None) -> l ) return dateParserList(result, ["time", "created_at"]) - def emptyDeviceData(self, deviceID: GenericID) -> str: + def emptyDeviceData(self, deviceID: GenericID, params: Optional[DeviceEmptyParams] = None) -> str: """ @description: Permanently removes all data from a device. This operation cannot be undone. + On Hybrid devices, pass params with route "mutable" or "immutable" to empty a + single side; omit it to remove all data. @see: https://help.tago.io/portal/en/kb/articles/device-data Device Data Management @@ -471,6 +474,7 @@ def emptyDeviceData(self, deviceID: GenericID) -> str: { "path": f"/device/{deviceID}/empty", "method": "POST", + "body": params, } ) return result diff --git a/tests/Resources/test_devices.py b/tests/Resources/test_devices.py index e700c74..fbbdca7 100644 --- a/tests/Resources/test_devices.py +++ b/tests/Resources/test_devices.py @@ -379,6 +379,21 @@ def testEmptyDeviceData(requests_mock: Mocker) -> None: assert result == "All data removed" +def testEmptyDeviceDataWithRoute(requests_mock: Mocker) -> None: + """Test emptyDeviceData with the hybrid route param in the request body.""" + device_id = "device-id-123" + requests_mock.post( + f"https://api.tago.io/device/{device_id}/empty", + json={"status": True, "result": "All data removed"}, + ) + + resources = Resources({"token": "your_token_value"}) + result = resources.devices.emptyDeviceData(device_id, {"route": "mutable"}) + + assert result == "All data removed" + assert requests_mock.last_request.json() == {"route": "mutable"} + + def testAmount(requests_mock: Mocker) -> None: """Test amount method of Devices class.""" device_id = "device-id-123"