@Reine_ABOU_SLEIMAN Reine did you get this to work?
Here is my Python script to import form Excel .xlsx file
Updated to add Tags which need to be in JSON format {“foo”:“Bar”}
################################################################################################################################
# V0.1 - Added support for tags which need to be JSON strin
# Python script to import Devices to an CS v4 Application from Excel .xlsx file
# requires uuid of application/device profile you can get from UI/Console
# E.g. application id: FFFFFF-b8bf-47c3-bcb1-686bc2fcAAA & device profile id:
#
# I can't find away to test if device entery exsists via get grpc.StatusCode.ALREADY_EXISTS:
# but grpc.StatusCode.INTERNAL: fires if Device exsists so that will have to surfice
# Applogies to any Pro Devloper this was put together by a scrippter!!
#
# Excel cols:
# dev_eui | application_id | device_profile_id | name | description | network_key | application_key | is_disabled | tags
# tag example: {"loc":"ii@St_Albans@GF@Study","device_details":"manf_Elsys,model_EMS,sn_174747,hw:_v1.1,fw:_v3","notes":" ..."}
################################################################################################################################
import openpyxl
import json
from chirpstack_api import api
import grpc
class DeviceImportRecord:
def __init__(self, dev_eui, application_id, device_profile_id, name, description, network_key, application_key,is_disabled,tags):
self.DevEUI = dev_eui
self.ApplicationID = application_id
self.DeviceProfileID = device_profile_id
self.Name = name
self.Description = description
self.NetworkKey = network_key
self.ApplicationKey = application_key
self.is_disabled = is_disabled
self.tags = tags
def get_device_import_list(file: str) -> list[DeviceImportRecord]:
out = []
try:
wb = openpyxl.load_workbook(file)
except Exception as e:
print("open excel file error",e)
return []
sheet = wb.active
rw_no = 0
rows = sheet.iter_rows(min_row=1,max_row=sheet.max_row)
for a,b,c,d,e,f,g,h,i in rows:
if rw_no > 0:
print('importing rw:',rw_no,':',a.value,b.value,c.value,d.value,e.value,f.value,g.value,h.value,i.value)
out.append(DeviceImportRecord(a.value,b.value,c.value,d.value,e.value,f.value,g.value,h.value,i.value))
rw_no += 1
return out
def import_devices(devices):
server = "localhost:8080"
api_token = "your API token"
channel = grpc.insecure_channel(server)
client = api.DeviceServiceStub(channel)
auth_token = [("authorization", "Bearer %s" % api_token)]
try:
req = api.CreateDeviceRequest()
for dev in devices:
print('creating Device with DevEUI:',dev.DevEUI)
req.device.dev_eui = str(dev.DevEUI)
req.device.name = str(dev.Name)
req.device.description = str(dev.Description)
req.device.application_id = str(dev.ApplicationID)
req.device.device_profile_id = str(dev.DeviceProfileID)
req.device.is_disabled = dev.is_disabled
req.device.tags.update(json.loads(dev.tags))
resp = client.Create(req, metadata=auth_token)
except grpc.RpcError as e:
#print('error:',type(e))
if e.code() == grpc.StatusCode.INTERNAL:
print('import error device',dev.DevEUI,' import aborted! Check Device my already exsist.')
try:
req = api.CreateDeviceKeysRequest()
for dev in devices:
print('creating keys for device DevEUI:',dev.DevEUI)
req.device_keys.dev_eui = str(dev.DevEUI)
req.device_keys.nwk_key = str(dev.NetworkKey)
req.device_keys.app_key = str(dev.ApplicationKey)
resp = client.CreateKeys(req, metadata=auth_token)
except grpc.RpcError as e:
print('error:',type(e))
return None
if __name__ == "__main__":
dev_list = get_device_import_list('/your path to/device_import.xlsx')
import_devices(dev_list)
Excel file