ON THIS PAGE
BLE Import (Use Case)
This Juniper Mist use case shows you how to efficiently import your Bluetooth Low Energy (BLE) assets with their names using the power of Juniper Mist Asset Visibility.
When you set up and activate location-based services with Juniper Mist Asset Visibility, admins like you can see all BLE clients and assets. You can also see their precise locations, right on an indoor floor plan or map.
For sites that use BLE asset tags, it’s handy to track these devices by giving them easily readable names that provide some context. You can add and display these names individually within the Juniper Mist portal, but if you have a lot of assets to manage, doing it one by one can be quite time consuming. An easier way to do this is to run a script to import BLE assets and assign them a name in bulk.
For this use case, you need to:
-
Enable Asset Visibility in the Site Settings for each site.
-
Make sure that you have an active license for Asset Visibility.
-
Make sure that you have placed compatible APs on the floor plan.
This use case involves two scripts: main.py and mist-client.py. A third file, a CSV file called assets.csv, contains the BLE assets and their corresponding names.
Here's the order of steps you follow when you need to import BLE assets:
-
Start by updating the main.py script with your Mist API token, Mist site universally unique identifier (UUID), and the region (or cloud) in which your organization is hosted.
-
Next, you add, remove, or inspect the BLE devices and their names within the assets.csv file.
-
Run the main.py script, which will use the CSV content to create the assets in Juniper Mist.
Main.py Script
A lot happens behind the scenes in the main.py script. The script imports the data from the CSV file and converts the data into JSON format. Then, for each device, the script creates a BLE asset and triggers the mist-client.py script. This mist-client.py script does the work of making all the necessary calls to the Juniper Mist API.
#!/usr/bin/python # # main.py # # Update main.py with your Mist API Token and Juniper Mist site UUID. # # Inspect the "assets.csv" file to update the assets being created, then run this exercise to automatically create BLE assets from CSV. import sys, csv, json, re from mist_client import Admin # Import the Juniper Mist client mist_api_token = '' # Your Juniper Mist API token goes here. Documentation: https://api.mist.com/api/v1/docs/Auth#api-token site_id = '' # Your Site ID goes here csv_file = 'assets.csv' # Convert CSV file to JSON object. def csv_to_json(file): csv_rows = [] with open(file) as csvfile: reader = csv.DictReader(csvfile) title = reader.fieldnames for row in reader: csv_rows.extend([ {title[i]: row[title[i]] for i in range(len(title))} ]) return csv_rows # Creates BLE assets using the given CSV file and the Juniper Mist API def create_assets(admin, data): for d in data: try: mac = re.sub(r'[^0-9a-fA-F]', '', d.get('MAC', '')).lower() assert len(mac) == 12 assert mac.isalnum() except: print('Invalid MAC {}, skipping this Asset.'.format(d.get('MAC', '(none)'))) continue # Build the asset payload payload = {'name': d['Name'].strip(), 'mac': mac} # Create the BLE Asset and note the targeted region (or cloud) api_url = 'https://api.mist.com/api/v1/sites/{}/assets'.format(site_id) (success, result) = admin.post(api_url, payload) # Add the new BLE Asset to the return list if result == None: print('Failed to create BLE Asset {}'.format(mac)) else: if success: print('Created BLE Asset \"{}\" ({})'.format(result.get('name', '(unnamed)'), result['mac'])) else: print('BLE Asset \"{}\" already exists with MAC Address {}'.format(d.get('Name', '(unnamed)'), mac)) # Main function if __name__ == '__main__': # Check for required variables if mist_api_token == '': print('Please provide your Mist API token as mist_api_token') sys.exit(1) elif site_id == '': print('Please provide your Mist Site UUID as site_id') sys.exit(1) # Create Mist client admin = Admin(mist_api_token) print() print('Converting file {} to JSON...\n'.format(csv_file)) # Convert CSV to valid JSON data = csv_to_json(csv_file) if data == None or data == []: print('Failed to convert CSV file to JSON. Exiting script.') sys.exit(2) print(json.dumps(data, indent=4, sort_keys=True)) print('\n=====\n') # Create the BLE Assets from CSV file print('Creating BLE Assets...\n') create_assets(admin, data) print()
Mist_client.py Script
The mist_client.py script functions like a regular RESTful client for interacting with the Juniper Mist API. The script makes API calls based on the input from the CSV file and the output of the main.py script. The mist-client.py script also error-checks the HTTP response from the API and displays the output, as follows:
#!/usr/bin/python # # mist_client.py # # Mist API client session. import json, requests # Mist CRUD operations class Admin(object): def __init__(self, token=''): self.session = requests.Session() self.headers = { 'Content-Type': 'application/json', 'Authorization': 'Token ' + token } def get(self, url): session = self.session headers = self.headers print('GET {}'.format(url)) response = session.get(url, headers=headers) if response.status_code != 200: print('Failed to GET') print('\tURL: {}'.format(url)) print('\tResponse: {} ({})'.format(response.text, response.status_code)) return False return json.loads(response.text) def post(self, url, payload, timeout=60): session = self.session headers = self.headers #print('POST {}'.format(url)) response = session.post(url, headers=headers, json=payload) if response.status_code == 400: return (False, response.text) elif response.status_code != 200: ''' print('Failed to POST') print('\tURL: {}'.format(url)) print('\tPayload: {}'.format(payload)) print('\tResponse: {} ({})'.format(response.text, response.status_code)) ''' return (False, None) return (True, json.loads(response.text))
Assets.csv
In this example, the assets.csv file resides in the same directory as the mist_client.py and main.py files. The following example shows how to format the CSV file with the name of the BLE asset and its associated MAC address:
Name,MAC Amber Badge,aa:bb:cc:dd:ee:ff Mark Badge,11-22-33-44-55-66 Invalid MAC,xx.yy.zz.xx.yy.zz
Automation goes beyond just using RESTful APIs and Python. Other options like WebSocket and webhook APIs are available. You can explore these other options for automation purposes.