Help with Python gRPC script for multicast group enqueue

Hi,

I used the example python code enqueue_downlink.py to send data to a device under my application. It is successfully queueing up the data. Now, added the same device to a Multicast-group and trying to enqueue data through python-gRPC API call EnqueueMulticastGroupQueueItemRequest.

But facing the “invalid wire type: LengthDelimited (expected Varint)” error while passing integer to f_port in my .py code . Error log attached below

Traceback (most recent call last):
File “/home/jaladmin/grpc/examples/python/helloworld/multicast.py”, line 92, in
resp = client.Enqueue(req, metadata=auth_token)
File “/home/jaladmin/.local/lib/python3.10/site-packages/grpc/_channel.py”, line 1176, in call
return _end_unary_response_blocking(state, call, False, None)
File “/home/jaladmin/.local/lib/python3.10/site-packages/grpc/_channel.py”, line 1005, in _end_unary_response_blocking
raise _InactiveRpcError(state) # pytype: disable=not-instantiable
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
status = StatusCode.INTERNAL
details = “failed to decode Protobuf message: DeviceQueueItem.f_port: EnqueueDeviceQueueItemRequest.queue_item: invalid wire type: LengthDelimited (expected Varint)”
debug_error_string = “UNKNOWN:Error received from peer {grpc_message:“failed to decode Protobuf message: DeviceQueueItem.f_port: EnqueueDeviceQueueItemRequest.queue_item: invalid wire type: LengthDelimited (expected Varint)”, grpc_status:13, created_time:“2024-02-29T17:41:09.880460327+05:30”}”

Passing varint encoded byte in f_port still getting the below error

Traceback (most recent call last):
File “/home/jaladmin/grpc/examples/python/helloworld/multicast.py”, line 89, in
req.queue_item.f_port = encode(10)
TypeError: ‘bytes’ object cannot be interpreted as an integer

Can someone help me with this

multicast.py

import os

# byte-oriented StringIO was moved to io.BytesIO in py3k
try:
    from io import BytesIO
except ImportError:
    from StringIO import StringIO as BytesIO

import grpc
from chirpstack_api import api

import sys

if sys.version > '3':
    def _byte(b):
        return bytes((b, ))
else:
    def _byte(b):
        return chr(b)


def encode(number):
    """Pack `number` into varint bytes"""
    buf = b''
    while True:
        towrite = number & 0x7f
        number >>= 7
        if number:
            buf += _byte(towrite | 0x80)
        else:
            buf += _byte(towrite)
            break
    return buf

def decode_stream(stream):
    """Read a varint from `stream`"""
    shift = 0
    result = 0
    while True:
        i = _read_one(stream)
        result |= (i & 0x7f) << shift
        shift += 7
        if not (i & 0x80):
            break

    return result

def decode_bytes(buf):
    """Read a varint from from `buf` bytes"""
    return decode_stream(BytesIO(buf))


def _read_one(stream):
    """Read a byte from the file (as an integer)

    raises EOFError if the stream ends while reading bytes.
    """
    c = stream.read(1)
    if c == b'':
        raise EOFError("Unexpected EOF while reading bytes")
    return ord(c)

# Configuration.

# This must point to the API interface.
server = "localhost:8080"

# The DevEUI for which you want to enqueue the downlink.
multicast_group_id = "f41bfaafc17a43db8f57006afcd33779" #"01b24837"


# The API token (retrieved using the web-interface).
api_token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJjaGlycHN0YWNrIiwiaXNzIjoiY2hpcnBzdGFjayIsInN1YiI6ImQ1NzAyMjMyLTBhYWYtNDY1NC1hOGM3LTFjYTBkYzA2Nzg2ZiIsInR5cCI6ImtleSJ9.Zswih1JndNV14s_LpPNGf9c3GM2hULw2RlsaqDxbE8Y"

if __name__ == "__main__":
  # Connect without using TLS.
  channel = grpc.insecure_channel(server)

  # Device-queue API client.
  client = api.DeviceServiceStub(channel)

  # Define the API key meta-data.
  auth_token = [("authorization", "Bearer %s" % api_token)]

  # Construct request.
  req = api.EnqueueMulticastGroupQueueItemRequest()

  req.queue_item.multicast_group_id = multicast_group_id
  req.queue_item.f_port = encode(10)
  req.queue_item.data = bytes([0x01, 0x02, 0x03])

  resp = client.Enqueue(req, metadata=auth_token)

  # Print the downlink id
  print(resp.id)


The issue is probably related to you creating the client with api.DeviceServiceStub(channel) rather than api.MulticastGroupServiceStub(channel). Depending on what section of the API protocol documentation your call falls under, you must use the appropriate service stub (I just learnt this solving a similar issue).