This csv_import.py example is perfect for teams that have data from offline devices. By importating them into the Client Portal, you can aggregate this data with your connected devices.

Before You Start:

<aside> 💡 If you and your users want to upload multiple CSVs and aggregate that data, the number f columns, the headers for each column, and the ordering for each column should match identically (character for chacter) betweeen your CSVs.

If there are differences between the CSVs, then when you to export the combined CSV data from the Client Portal application, your data will not be aligned in a useful way.

</aside>

Running the Example

  1. Copy the code example (below) to your laptop (or whichever device you will be uploading your CSV from). You do not need to modify the file in any way to use it.

  2. Open a terminal window in the same folder of the CSV file and launch the script from the command prompt using this format:

    python csv_import.py -f filename.csv -s pcbSn

    1. Replace “filename.csv” with the local filename you want to import to the Client Portal.
    2. Replace “pcbSn” with the value of the device you registered in the Client Portal’s “Manage Boards” pane.
  3. A succesful import will output Post Data: <Response [200]> to your terminal window for every row of data in the CSV file successfully posted to the Client Portal. In this example, we can see the CSV file had three rows, and each row was successfully posted to the Client Portal:

    Post Data:  <Response [200]>
    Post Data:  <Response [200]>
    Post Data:  <Response [200]>
    
    Complete.
    

Code Example

#!/usr/bin/python3
# Python 3.9.2 or above
#
# csv_import.py
#
# Usage:
#
# python device_postcsv.py -s <pcbSN> -f <path/filename>
#
# For Help:
#
# python device_postcsv.py -h
#
# This example showcases posting CSV data to a device record at iot.edglab.com
#
# Dependencies:
#
# $ pip install argparse
# $ pip install dateparser
# $ pip install requests

#
# Copyright © 2021-2023 Engineering Design Group, LLC. You have the right to copy and use this code.
#

import requests
import json
from datetime import datetime
import dateparser as parser
import csv
import argparse
# from pprint import pprint as pprint

def createPostData(dataDict, pcbSN):
    """Package up the data to send from a dict"""
    ts = str(datetime.utcnow().isoformat())
    datestr = ''
    if "Timestamp" in dataDict :
        ts = dataDict['Timestamp']
    if "timestamp" in dataDict :
        ts = dataDict['timestamp']
    if "Time" in dataDict :
        ts = dataDict['Time']
    if "time" in dataDict :
        ts = dataDict['time']
    if "datetime" in dataDict :
        ts = dataDict['datetime']
    if "Date" in dataDict :
        datestr = dataDict['Date']
    if "date" in dataDict :
        datestr = dataDict['date']
    if ts.isnumeric() :
        datetime_obj=datetime.fromtimestamp(int(ts))
        ts = str(datetime_obj.isoformat())
    elif datestr != '' and  'T' not in ts:
        datetimeParsed = parser.parse(datestr + 'T' + ts)
        ts = str(datetimeParsed.isoformat())
    packagedData = {
        'pcbSn': pcbSN,
        'timeSent': ts,
        "dataList": dataDict
    }

    return packagedData

def API_postData(packagedData):

    #generate URL for POST request
    baseUrl = "<https://iot.edglab.com>"
    endpointAddress = "/api/boarddata"
    dataUrl = baseUrl + endpointAddress

    #generate header (auth token is not required)
    header = {
        "Content-Type": "application/json"
    }

    # debug statements below
#     print(dataUrl)
#     print(header)
#     print(json.dumps(packagedData))

    #send Data to API through POST request
    response = requests.post(dataUrl,
                            headers = header,
                            data = json.dumps(packagedData),
                            verify = True)

    print("Post Data: ", response)
    return response

def main():

    # get input file name and pcbSN
    parser = argparse.ArgumentParser() #initialize argument parser
    parser.add_argument("-f", "--file", dest = "filePath", required=True, help="path/file to upload as device data")
    parser.add_argument("-s", "--pcbsn", dest = "pcbSN", required=True, help="pcbSn aka serial number of the device for this data")

    args = parser.parse_args()

    with open( args.filePath, 'r', encoding='utf-8-sig') as theFile:
        reader = csv.DictReader(theFile)
        for line in reader:
            #pprint(line)
            #print("Packaging device data...")
            #package the device Data into a format the API recognizes
            packaged_data = createPostData(line, args.pcbSN)

            #print("Posting data to API...")
            #post the packaged data to the API
            data = API_postData(packaged_data)

    print("\\n   Complete.\\n")

if __name__ == "__main__":
    main()