Help with Python gRPC script for updating device tags

I figured out how to use gPRC in Python to query devices, but I can’t figure out how to update device. Below is my code snippet which is returning an error at response = client.Update(). I thought the error might be due to the dev_eui number however, the same number works when used with GetDeviceRequest().

Error: invalid length: expected length 32 for simple format, found 0

Code:

import grpc
from chirpstack_api import api as chirpstack

# Define device EUI and new tags
device_eui = "a80251d9a1885759"   #note - number altered for security purposes
new_tags = {
    "Row": "22",
    "Compost ID": "9999"
}

# Create an insecure gRPC channel
channel = grpc.insecure_channel(SERVER)

# Create a gRPC client stub
client = chirpstack.device_pb2_grpc.DeviceServiceStub(channel)

# Define the API key metadata
auth_token = [("authorization", f"Bearer {API_TOKEN}")]

# Create updated device object with new tags
updated_device = chirpstack.device_pb2.Device()
updated_device.dev_eui = device_eui
updated_device.tags.update(new_tags)

# Build update request object
request = chirpstack.device_pb2.UpdateDeviceRequest(device=updated_device)

# Send request and get response
response = client.Update(request, metadata=auth_token)

if response.success:
    print(f"Successfully updated tags for device {device_eui.decode()}")
else:
    print(f"Error updating tags: {response.error}")

# Close the gRPC channel
channel.close()

I don’t know the Python gRPC libraries, and that error is a bit vague, but a missing length of 32 seems like you may be missing a 16-byte UUID. Perhaps the Application or Device Profile ID?

https://www.chirpstack.io/docs/chirpstack/api/api.html#api-Device

Are you retrieving the device first to populate your object and then updating the tags before sending it back?

1 Like

I’m not a python guy but was able to create an bulk import from Excel
@bconway is right you need Application AND Device Profile UUID
Tags need to be JSON.

This might help

1 Like

@bconway and @iiLaw thank you! In addition to your comments, the Device Name is also required. Plus the device description and all of the tags need to be included within UpdateDeviceRequest otherwise they get removed from the device. I’m posting my final working code in case anyone else needs it.

channel = grpc.insecure_channel(SERVER)
client = chirpstack.DeviceServiceStub(channel)
auth_token = [("authorization", f"Bearer {API_TOKEN}")]

try:
    req = chirpstack.UpdateDeviceRequest()
    req.device.dev_eui           = "a84041d9a1800000"
    req.device.name              = "Device Name"
    req.device.description       = "This is my device description"
    req.device.application_id    = "COMPOST_SENSOR_APP_ID"
    req.device.device_profile_id = "972dd6d0-7c7d-4ee9-aba8-8b34351d000e"
    # req.device.is_disabled       = dev.is_disabled                     
    req.device.tags.update(json.loads('{"Row": 20, "Compost ID": 9999}'))
    resp = client.Update(req, metadata=auth_token)
except Exception as error:
    print("An exception occured:", error)

channel.close()
2 Likes