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.
<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>
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.
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
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.
#!/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()