470 lines
20 KiB
Plaintext
470 lines
20 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from tb_rest_client.rest_client_pe import *\n",
|
|
"from tb_rest_client.rest import ApiException\n",
|
|
"\n",
|
|
"import json, sys, os\n",
|
|
"from datetime import datetime as dt"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"url = \"https://hp.henrypump.cloud\"\n",
|
|
"username = \"nmelone@henry-pump.com\"\n",
|
|
"password = \"gzU6$26v42mU%3jDzTJf\""
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#Creating Rest Client for ThingsBoard\n",
|
|
"with RestClientPE(base_url=url) as rest_client:\n",
|
|
" try:\n",
|
|
" rest_client.login(username=username, password=password)\n",
|
|
" #Loading Config from file\n",
|
|
" with open(\"./config.json\") as f:\n",
|
|
" config = json.load(f)\n",
|
|
"\n",
|
|
" reportData = {}\n",
|
|
" reportToList = {}\n",
|
|
" #Loop through each item in config, each item represents a report\n",
|
|
" for report in config:\n",
|
|
" reportToList[report[\"name\"]] = report[\"emails\"]\n",
|
|
" #Each customer becomes it's own xlsx file later\n",
|
|
" for customer in report[\"customers\"].keys():\n",
|
|
" #Get all the devices for a given customer\n",
|
|
" devices = rest_client.get_customer_devices(customer_id=customer, page=0, page_size=100)\n",
|
|
" #Filter devices to the desired devices\n",
|
|
" if report[\"filterDevicesIn\"]:\n",
|
|
" devices.data = [device for device in devices.data if device.id.id in report[\"filterDevicesIn\"]]\n",
|
|
" if report[\"filterDevicesOut\"]:\n",
|
|
" devices.data = [device for device in devices.data if device.id.id not in report[\"filterDevicesOut\"]]\n",
|
|
" #Create the report in reportData if needed\n",
|
|
" if not reportData.get(report[\"name\"], None):\n",
|
|
" reportData[report[\"name\"]] = {}\n",
|
|
" #Go through all the devices and add them and their desired data to reportData \n",
|
|
" for device in devices.data:\n",
|
|
" name = device.name\n",
|
|
" keys = rest_client.get_timeseries_keys_v1(device.id)\n",
|
|
" #Filter keys to desired keys\n",
|
|
" for deviceType in report[\"customers\"][customer][\"deviceTypes\"]:\n",
|
|
" if device.type == deviceType[\"deviceType\"]:\n",
|
|
" keys = list(filter(lambda x: x in deviceType[\"dataPoints\"], keys))\n",
|
|
" #Create customer if needed\n",
|
|
" if not reportData[report[\"name\"]].get(report[\"customers\"][customer][\"name\"], None):\n",
|
|
" reportData[report[\"name\"]][report[\"customers\"][customer][\"name\"]] = {}\n",
|
|
" #Check to make sure the deviceType is desired in the report for the given device\n",
|
|
" if device.type in list(map(lambda x: x[\"deviceType\"], report[\"customers\"][customer][\"deviceTypes\"])):\n",
|
|
" #Create deviceType if needed\n",
|
|
" if not reportData[report[\"name\"]][report[\"customers\"][customer][\"name\"]].get(device.type, None):\n",
|
|
" reportData[report[\"name\"]][report[\"customers\"][customer][\"name\"]][device.type] = {}\n",
|
|
" reportData[report[\"name\"]][report[\"customers\"][customer][\"name\"]][device.type][device.name] = rest_client.get_latest_timeseries(entity_id=device.id , keys=\",\".join(keys))\n",
|
|
" except ApiException as e:\n",
|
|
" print(e)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"{\n",
|
|
" \"CrownQuest-Daily-Report\": {\n",
|
|
" \"CrownQuest\": {\n",
|
|
" \"rigpump\": {\n",
|
|
" \"#07\": {\n",
|
|
" \"vfd_frequency\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721761800000,\n",
|
|
" \"value\": \"0.0\"\n",
|
|
" }\n",
|
|
" ],\n",
|
|
" \"vfd_current\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721761800000,\n",
|
|
" \"value\": \"0.0\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" },\n",
|
|
" \"#03\": {\n",
|
|
" \"vfd_frequency\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721712600000,\n",
|
|
" \"value\": \"0.0\"\n",
|
|
" }\n",
|
|
" ],\n",
|
|
" \"vfd_current\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721712600000,\n",
|
|
" \"value\": \"0.0\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" },\n",
|
|
" \"#04\": {\n",
|
|
" \"vfd_frequency\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"0.0\"\n",
|
|
" }\n",
|
|
" ],\n",
|
|
" \"vfd_current\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"0.0\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" },\n",
|
|
" \"#08\": {\n",
|
|
" \"vfd_frequency\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"0.0\"\n",
|
|
" }\n",
|
|
" ],\n",
|
|
" \"vfd_current\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"0.0\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" },\n",
|
|
" \"#12\": {\n",
|
|
" \"vfd_frequency\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772000000,\n",
|
|
" \"value\": \"40.98\"\n",
|
|
" }\n",
|
|
" ],\n",
|
|
" \"vfd_current\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772000000,\n",
|
|
" \"value\": \"43.03\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" },\n",
|
|
" \"#11\": {\n",
|
|
" \"vfd_frequency\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"0.0\"\n",
|
|
" }\n",
|
|
" ],\n",
|
|
" \"vfd_current\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"0.0\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" },\n",
|
|
" \"#06\": {\n",
|
|
" \"vfd_frequency\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"50.0\"\n",
|
|
" }\n",
|
|
" ],\n",
|
|
" \"vfd_current\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"34.51\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" },\n",
|
|
" \"#10\": {\n",
|
|
" \"vfd_frequency\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"0.0\"\n",
|
|
" }\n",
|
|
" ],\n",
|
|
" \"vfd_current\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"0.0\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" },\n",
|
|
" \"#13\": {\n",
|
|
" \"vfd_frequency\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"0.0\"\n",
|
|
" }\n",
|
|
" ],\n",
|
|
" \"vfd_current\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"0.0\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" }\n",
|
|
" },\n",
|
|
" \"cqwatertanks\": {\n",
|
|
" \"Office Water Management\": {\n",
|
|
" \"fm_1_flow_rate\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"165.81\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" }\n",
|
|
" }\n",
|
|
" },\n",
|
|
" \"Henry-Petroleum\": {\n",
|
|
" \"abbflow\": {\n",
|
|
" \"Davis Check Meter\": {\n",
|
|
" \"accumulated_volume\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772000000,\n",
|
|
" \"value\": \"366655.72\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" },\n",
|
|
" \"Great Western Check Meter\": {\n",
|
|
" \"accumulated_volume\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721716800000,\n",
|
|
" \"value\": \"45504.62\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" },\n",
|
|
" \"Francis Hill Check Meter\": {\n",
|
|
" \"accumulated_volume\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"340350.0\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" },\n",
|
|
" \"Foundation Check Meter\": {\n",
|
|
" \"accumulated_volume\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"434597.88\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" },\n",
|
|
" \"Wess Hill Check Meter\": {\n",
|
|
" \"accumulated_volume\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"226273.38\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" },\n",
|
|
" \"Lively Check Meter\": {\n",
|
|
" \"accumulated_volume\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"233637.39\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" },\n",
|
|
" \"Glasscock Check Meter\": {\n",
|
|
" \"accumulated_volume\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"128745.13\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" },\n",
|
|
" \"Mann Check Meter\": {\n",
|
|
" \"accumulated_volume\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772600000,\n",
|
|
" \"value\": \"29861.7\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" }\n",
|
|
" }\n",
|
|
" }\n",
|
|
" },\n",
|
|
" \"Henry-Petroleum-Daily-Report\": {\n",
|
|
" \"Henry-Petroleum\": {\n",
|
|
" \"abbflow\": {\n",
|
|
" \"Davis Check Meter\": {\n",
|
|
" \"accumulated_volume\": [\n",
|
|
" {\n",
|
|
" \"ts\": 1721772000000,\n",
|
|
" \"value\": \"366655.72\"\n",
|
|
" }\n",
|
|
" ]\n",
|
|
" }\n",
|
|
" }\n",
|
|
" }\n",
|
|
" }\n",
|
|
"}\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(json.dumps(reportData, indent=4))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"{\n",
|
|
" \"CrownQuest-Daily-Report\": [\n",
|
|
" \"nmelone@henry-pump.com\",\n",
|
|
" \"n_melone@hotmail.com\"\n",
|
|
" ],\n",
|
|
" \"Henry-Petroleum-Daily-Report\": [\n",
|
|
" \"nmelone@henry-pump.com\",\n",
|
|
" \"nmelone08@gmail.com\"\n",
|
|
" ]\n",
|
|
"}\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(json.dumps(reportToList, indent=4))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import xlsxwriter\n",
|
|
"import boto3\n",
|
|
"from email.mime.multipart import MIMEMultipart\n",
|
|
"from email.mime.application import MIMEApplication\n",
|
|
"from email.mime.text import MIMEText\n",
|
|
"import tempfile\n",
|
|
"from email import encoders\n",
|
|
"from email.mime.base import MIMEBase"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Create an AWS SES client\n",
|
|
"ses_client = boto3.client('ses', region_name='us-east-1')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"{'MessageId': '01000190e1a66884-79debb77-9a2f-400a-927e-ed2fe315a32c-000000', 'ResponseMetadata': {'RequestId': '212bf456-644c-492d-acf3-d23255222e4d', 'HTTPStatusCode': 200, 'HTTPHeaders': {'date': 'Tue, 23 Jul 2024 22:11:37 GMT', 'content-type': 'text/xml', 'content-length': '338', 'connection': 'keep-alive', 'x-amzn-requestid': '212bf456-644c-492d-acf3-d23255222e4d'}, 'RetryAttempts': 0}}\n",
|
|
"[<xlsxwriter.workbook.Workbook object at 0x1100dae40>, <xlsxwriter.workbook.Workbook object at 0x105820980>]\n",
|
|
"{'MessageId': '01000190e1a66958-70b625d5-dec6-45f1-a1d8-155264b5c6f0-000000', 'ResponseMetadata': {'RequestId': '9de5509b-9745-4379-93d1-535e055bf55e', 'HTTPStatusCode': 200, 'HTTPHeaders': {'date': 'Tue, 23 Jul 2024 22:11:38 GMT', 'content-type': 'text/xml', 'content-length': '338', 'connection': 'keep-alive', 'x-amzn-requestid': '9de5509b-9745-4379-93d1-535e055bf55e'}, 'RetryAttempts': 0}}\n",
|
|
"[<xlsxwriter.workbook.Workbook object at 0x105f2afc0>]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Create a workbook for each report\n",
|
|
"for report_name, report_data in reportData.items():\n",
|
|
" #will generate an email lower down\n",
|
|
" spreadsheets = []\n",
|
|
" # Create a worksheet for each company\n",
|
|
" for company_name, company_data in report_data.items():\n",
|
|
" workbook = xlsxwriter.Workbook(f\"{report_name}-{company_name}-{dt.today().strftime('%Y-%m-%d')}.xlsx\")\n",
|
|
" bold = workbook.add_format({'bold': True})\n",
|
|
" # Create a sheet for each device type\n",
|
|
" for device_type, device_data in company_data.items():\n",
|
|
" worksheet = workbook.add_worksheet(device_type)\n",
|
|
" \n",
|
|
" # Set the header row with device types\n",
|
|
" device_types = list(device_data.keys())\n",
|
|
" worksheet.write_column(1, 0, device_types,bold)\n",
|
|
" \n",
|
|
" # Write the data to the sheet\n",
|
|
" for i, (telemetry_name, telemetry_data) in enumerate(device_data.items()):\n",
|
|
" # Set the header row with telemetry names\n",
|
|
" telemetry_names = list(telemetry_data.keys())\n",
|
|
" worksheet.write_row(0, 1, telemetry_names, bold)\n",
|
|
" for j, (data_name, data) in enumerate(telemetry_data.items()):\n",
|
|
" values = [d[\"value\"] for d in data]\n",
|
|
" worksheet.write_row(i + 1, j+ 1, values)\n",
|
|
" worksheet.autofit()\n",
|
|
" workbook.close()\n",
|
|
" spreadsheets.append(workbook)\n",
|
|
" # Create an email message\n",
|
|
" msg = MIMEMultipart()\n",
|
|
" msg['Subject'] = report_name\n",
|
|
" msg['From'] = 'alerts@henry-pump.com'\n",
|
|
" msg['To'] = \", \".join(reportToList[report_name])\n",
|
|
"\n",
|
|
" # Add a text body to the message (optional)\n",
|
|
" body_text = 'Please find the attached spreadsheets.'\n",
|
|
" msg.attach(MIMEText(body_text, 'plain'))\n",
|
|
"\n",
|
|
" # Attach each workbook in the spreadsheets array\n",
|
|
" for spreadsheet in spreadsheets:\n",
|
|
" # Attach the file to the email message\n",
|
|
" attachment = MIMEBase('application', 'octet-stream')\n",
|
|
" attachment.set_payload(open(spreadsheet.filename, \"rb\").read())\n",
|
|
" encoders.encode_base64(attachment)\n",
|
|
" attachment.add_header('Content-Disposition', 'attachment', filename=spreadsheet.filename)\n",
|
|
"\n",
|
|
" msg.attach(attachment)\n",
|
|
"\n",
|
|
" # Send the email using AWS SES\n",
|
|
" response = ses_client.send_raw_email(\n",
|
|
" \n",
|
|
" RawMessage={'Data': msg.as_string()}\n",
|
|
" )\n",
|
|
"\n",
|
|
" print(response)\n",
|
|
" print(spreadsheets)"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "thingsboard",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.12.4"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
}
|