├── API_Gateway_Direct ├── ESP32-to-API-Gateway.ino ├── ESP32-to-API-Key-Secured.ino ├── ESP8266-to-API-Gateway-direct.ino ├── ESP8266-to-API-Key-Secured.ino ├── My-Arduino-lambda-Proxy.js └── Visualizations │ ├── Chartjs │ ├── CORS.json │ ├── index.html │ ├── main.js │ └── visualizer.js │ └── Highcharts │ ├── CORS.json │ └── index.html ├── AWSCLI_Test_Payload ├── Advanced_IoTAnalytics ├── API_Key_Secured_index.html ├── CORS.json ├── GPS_Sketch_ESP32.ino ├── GPS_Sketch_ESP8266.ino ├── extract_csv-data-Lambda.js ├── index.html ├── test_payload.json └── transformLambda.js ├── Basic_IoT_Analytics ├── index.html ├── oldSagemaker_Py2.7 ├── old_index.html └── sagemaker.py ├── ESP32-to-AWS-IoT ├── ESP32toAWS-No_Formatting_required.ino ├── ESP8266-to-AWS-IoT ├── ESP_No_Cert_Formatting ├── ESP32toAWS-No_Formatting_required.ino ├── ESP8266_version_3+_by_ESP8266_Community │ ├── ESP8266_to_AWS_IoT_Core.ino │ └── README.md ├── ESP8266toAWS-No_Formatting_required.ino └── README.md ├── GoogleCharts_CSV.html ├── Guitar_refactored ├── Attach2LambdaPolicy.json ├── CORS.json ├── index.html ├── index.js ├── payload.json └── refresh.js ├── IoT_Sample_Data_Publishers ├── Bash_IoT_AWCLI2.sh ├── Bash_IoT_Local_Publisher.sh ├── Local_Publisher │ ├── README.md │ ├── raw_data_small.json │ └── send_sample_messages.py ├── SImulate_Device_In_Lambda_on_AWS.py └── Simulate_Device_requires_certs.py ├── IoT_Visualizer_Form_Lambda ├── CORS.json ├── index.html ├── main.js ├── publicBucketPolicy.json └── visualizer.js ├── KinesisFirehose_Visualizer ├── CORS.json ├── index.html ├── main.js └── visualizer.js ├── Lambda_Publisher ├── IoT-Publisher_NonAsync.js ├── IoT_Pubisher.js ├── IoT_Publisher.py └── websiteInputBox.html ├── Level3_design ├── CORS.json ├── index.html ├── index.js └── oldCombinedfiles.html ├── Level4_design ├── 1_Synchronous_IoT │ ├── CORS.json │ ├── IoT_Payload_Producer.sh │ ├── Open_Bucket_Policy.json │ ├── README.md │ ├── Timestamp_to_time.js │ ├── index.html │ ├── main.js │ └── timestamp_RulesQueryStatement ├── 2_ Asynchronous_IoT_Beginner │ ├── Basic_website │ │ └── README.md │ ├── Better_website │ │ ├── README.md │ │ ├── index.html │ │ └── main.js │ ├── CORS.json │ ├── IoT_Bash_Producer.sh │ ├── IoT_Core_Rules_Query_Statement.sql │ ├── IoT_Test_Payload.json │ ├── Open_Bucket_Policy.json │ ├── README.md │ ├── Test_Script_for_Browser.js │ ├── Test_index_for_browser.html │ ├── connection_Lambda.js │ ├── index.html │ ├── main.js │ └── send_IoT_Message_Lambd.py ├── 3_ Asynchronous_IoT_Intermediate │ ├── Basic_website │ │ ├── README.md │ │ ├── index.html │ │ └── main.js │ ├── Better_website │ │ ├── README.md │ │ ├── index.html │ │ └── main.js │ ├── CORS.json │ ├── Chartjs_Streaming │ │ ├── README.md │ │ ├── index.html │ │ └── main.js │ ├── Cloudboard │ │ ├── Arduino │ │ │ ├── Cloudboard_to_AWS.ino │ │ │ ├── README.md │ │ │ └── images.h │ │ ├── Highcharts │ │ │ ├── index.html │ │ │ └── main.js │ │ ├── Lambdas │ │ │ ├── connection.js │ │ │ └── sendIoTdata.py │ │ ├── Plotly │ │ │ ├── guages.js │ │ │ └── index.html │ │ ├── README.md │ │ └── S3-Website-Setup-files │ │ │ ├── CORS.json │ │ │ ├── Public_Bucket_Policy.json │ │ │ └── README.md │ ├── Google_Chart │ │ ├── index.html │ │ └── main.js │ ├── HighCharts_Streaming_WebSockets │ │ ├── README.md │ │ ├── index.html │ │ └── main.js │ ├── MQTT_Messaging_Lambdas │ │ ├── README.md │ │ ├── connection.js │ │ └── sendiotpayload.py │ ├── Open_Bucket_Policy.json │ ├── PlotlyGraph_Streaming │ │ ├── Device_side_timestamp │ │ │ ├── index.html │ │ │ └── main.js │ │ ├── Guages&line │ │ │ ├── README.md │ │ │ ├── guages.js │ │ │ └── index.html │ │ ├── README.md │ │ ├── index.html │ │ └── main.js │ ├── README.md │ ├── RQS.sql │ ├── Smoothie_Chart │ │ ├── README.md │ │ ├── index.html │ │ └── smoothie.js │ ├── connection_Lambda2.js │ ├── index.html │ ├── iot_tester.sh │ ├── main.js │ ├── online_wss_tester_payload.json │ ├── result.md │ ├── sendiotmessage_lambda2.py │ └── test_payload.json ├── IMG_4147.jpg ├── README.md └── resize15.jpg ├── Mqtt-serverless-Paho-broker ├── PubSub_Troubleshooting ├── PublicBucket ├── AWS_CLI_Commands │ └── README.md ├── LimitByIPBucketPolicy ├── PublicBucketReadPolicy ├── PublicReadCORS └── README.md ├── README.md ├── S3lambdaManyFolders.js ├── ShadowState ├── BasicPubSub │ ├── ESP8266Publisher.ino │ └── ESP8266Subscriber.ino └── MultiTopics │ ├── ESP8266_Publisher.ino │ ├── ESP8266_Subscriber.ino │ ├── Republish_SQL │ └── testPayload.json ├── docs ├── index.html └── test2 │ └── index.html ├── myNode_IoT_Lambda ├── myS3lambda.js ├── security ├── Add_API_Key ├── BucketPolicy_IPAdress ├── Folder_Tagging.md └── README.rst ├── simPub_ESP32.ino ├── simPub_ESP8266.ino └── troubleshooting_device_connections /API_Gateway_Direct/ESP32-to-API-Gateway.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Rui Santos 3 | Complete project details at Complete project details at https://RandomNerdTutorials.com/esp32-http-get-post-arduino/ 4 | 5 | Modified by Stephen Borsay for AWS Gateway 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files. 8 | 9 | The above copyright notice and this permission notice shall be included in all 10 | copies or substantial portions of the Software. 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | const char* ssid = ""; 17 | const char* password = ""; 18 | 19 | //Your Domain name with URL path or IP address with path 20 | String serverName = "https://hxxxxsc.execute-api.us-east-2.amazonaws.com/depA"; //fill this out with your own API GAteway deployment 21 | 22 | // the following variables are unsigned longs because the time, measured in 23 | // milliseconds, will quickly become a bigger number than can be stored in an int. 24 | unsigned long lastTime = 0; 25 | // Timer set to 10 minutes (600000) 26 | //unsigned long timerDelay = 600000; 27 | // Set timer to 5 seconds (5000) 28 | unsigned long timerDelay = 5000; 29 | unsigned long Uptime; 30 | 31 | void setup() { 32 | Serial.begin(115200); 33 | 34 | WiFi.begin(ssid, password); 35 | Serial.println("Connecting"); 36 | while(WiFi.status() != WL_CONNECTED) { 37 | delay(500); 38 | Serial.print("."); 39 | } 40 | Serial.println(""); 41 | Serial.print("Connected to WiFi network with IP Address: "); 42 | Serial.println(WiFi.localIP()); 43 | 44 | Serial.println("Timer set to 5 seconds (timerDelay variable), it will take 5 seconds before publishing the first reading."); 45 | } 46 | 47 | void loop() { 48 | int t = random(30,110); //fake number range, adjust as you like 49 | int h = random(50,100); 50 | Uptime = millis()/1000; 51 | //Send an HTTP POST request every 10 minutes 52 | if ((millis() - lastTime) > timerDelay) { 53 | //Check WiFi connection status 54 | if(WiFi.status()== WL_CONNECTED){ 55 | HTTPClient http; 56 | 57 | 58 | String serverPath = serverName + "/?uptime=" + (String) Uptime 59 | + "&temperature=" + (String) t + "&humidity=" + (String) h; 60 | 61 | // Your Domain name with URL path or IP address with path 62 | http.begin(serverPath.c_str()); 63 | 64 | // Send HTTP GET request 65 | int httpResponseCode = http.GET(); 66 | 67 | if (httpResponseCode>0) { 68 | Serial.print("HTTP Response code: "); 69 | Serial.println(httpResponseCode); 70 | String payload = http.getString(); 71 | Serial.println(payload); 72 | } 73 | else { 74 | Serial.print("Error code: "); 75 | Serial.println(httpResponseCode); 76 | } 77 | // Free resources 78 | http.end(); 79 | } 80 | else { 81 | Serial.println("WiFi Disconnected"); 82 | } 83 | lastTime = millis(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /API_Gateway_Direct/ESP32-to-API-Key-Secured.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Rui Santos 3 | Complete project details at Complete project details at https://RandomNerdTutorials.com/esp32-http-get-post-arduino/ 4 | 5 | Modified for AWS API Gateway by Stephen Borsay teaching AWS IoT on Udemy.com 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files. 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | const char* ssid = ""; 18 | const char* password = ""; 19 | 20 | //Your Domain name with URL path or IP address with path 21 | String serverName = "https://h2ff645sc.execute-api.us-east-2.amazonaws.com/deploymentA"; //aws API Gateway url, Need htps:// pre-fix for ESP32 sketch 22 | const char* API_KEY = "mnCvfHgNtiFgRtn71DHn8EcUBEhcFBfcY0JnJ50"; //Your AWS API-Key 23 | 24 | // the following variables are unsigned longs because the time, measured in 25 | // milliseconds, will quickly become a bigger number than can be stored in an int. 26 | unsigned long lastTime = 0; 27 | // Timer set to 10 minutes (600000) 28 | //unsigned long timerDelay = 600000; 29 | // Set timer to 5 seconds (5000) 30 | unsigned long timerDelay = 5000; 31 | unsigned long Uptime; 32 | 33 | void setup() { 34 | Serial.begin(115200); 35 | 36 | WiFi.begin(ssid, password); 37 | Serial.println("Connecting"); 38 | while(WiFi.status() != WL_CONNECTED) { 39 | delay(500); 40 | Serial.print("."); 41 | } 42 | Serial.println(""); 43 | Serial.print("Connected to WiFi network with IP Address: "); 44 | Serial.println(WiFi.localIP()); 45 | 46 | Serial.println("Timer set to 5 seconds (timerDelay variable), it will take 5 seconds before publishing the first reading."); 47 | } 48 | 49 | void loop() { 50 | 51 | int t = random(30,110); //fake number range, adjust as you like 52 | int h = random(50,100); 53 | 54 | Uptime = millis()/1000; 55 | 56 | //Send an HTTP POST request every 10 minutes 57 | if ((millis() - lastTime) > timerDelay) { 58 | //Check WiFi connection status 59 | if(WiFi.status()== WL_CONNECTED){ 60 | HTTPClient http; 61 | 62 | String serverPath = serverName + "/?uptime=" + (String) Uptime 63 | + "&temperature=" + (String) t + "&humidity=" + (String) h; 64 | http.addHeader("x-api-key", API_KEY); 65 | 66 | // Your Domain name with URL path or IP address with path 67 | http.begin(serverPath.c_str()); 68 | 69 | // Send HTTP GET request 70 | int httpResponseCode = http.GET(); 71 | 72 | if (httpResponseCode>0) { 73 | Serial.print("HTTP Response code: "); 74 | Serial.println(httpResponseCode); 75 | String payload = http.getString(); 76 | Serial.println(payload); 77 | } 78 | else { 79 | Serial.print("Error code: "); 80 | Serial.println(httpResponseCode); 81 | } 82 | // Free resources 83 | http.end(); 84 | } 85 | else { 86 | Serial.println("WiFi Disconnected"); 87 | } 88 | lastTime = millis(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /API_Gateway_Direct/ESP8266-to-API-Gateway-direct.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | //https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/HTTPSRequest/HTTPSRequest.ino 4 | HTTP over TLS (HTTPS) example sketch 5 | This example demonstrates how to use 6 | WiFiClientSecure class to access HTTPS API. 7 | We fetch and display the status of 8 | esp8266/Arduino project continuous integration 9 | build. 10 | Limitations: 11 | only RSA certificates 12 | no support of Perfect Forward Secrecy (PFS) 13 | TLSv1.2 is supported since version 2.4.0-rc1 14 | Created by Ivan Grokhotkov, 2015. 15 | This example is in public domain. 16 | 17 | * This example modified by Stephen Borsay for AWS Serverless course on Udemy 18 | * to Connect your device directly to AWS API Gateway 19 | *connect any sensor as desired 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #ifndef STASSID 26 | #define STASSID "" 27 | #define STAPSK "" 28 | #endif 29 | 30 | const char* ssid = STASSID; 31 | const char* password = STAPSK; 32 | const char* host = ".execute-api..amazonaws.com"; //do not include "https://" 33 | String url = ""; 34 | 35 | const int httpsPort = 443; 36 | unsigned long uptime; 37 | 38 | // Use web browser to view and copy SHA1 fingerprint of the certificate 39 | //to acquire the thumbprint for this webpage, go to the breadcrumbs in the upper right corner of your browser. 40 | //Then go to Tools-->developer tools-->security-->view certificate-->details(tab)-->thumbprint 41 | //const char fingerprint[] PROGMEM = "98 f8 5e fc 87 65 43 5f 0f c1 1e fe e9 81 c9 9c c2 43 27 4c"; //example thumbprint with proper formatting 42 | const char fingerprint[] PROGMEM = ""; 43 | 44 | WiFiClientSecure client; 45 | 46 | void setup() { 47 | Serial.begin(115200); 48 | Serial.println(); 49 | Serial.print("connecting to "); 50 | Serial.println(ssid); 51 | WiFi.mode(WIFI_STA); 52 | WiFi.begin(ssid, password); 53 | while (WiFi.status() != WL_CONNECTED) { 54 | delay(500); 55 | Serial.print("."); 56 | } 57 | Serial.println(""); 58 | Serial.println("WiFi connected"); 59 | Serial.println("IP address: "); 60 | Serial.println(WiFi.localIP()); 61 | 62 | // Use WiFiClientSecure class to create TLS connection 63 | 64 | Serial.print("connecting to "); 65 | Serial.println(host); 66 | 67 | Serial.printf("Using fingerprint '%s'\n", fingerprint); 68 | client.setFingerprint(fingerprint); 69 | 70 | if (!client.connect(host, httpsPort)) { 71 | Serial.println("connection failed"); 72 | return; 73 | } 74 | 75 | Serial.print("requesting URL: "); 76 | Serial.println(url); 77 | 78 | } 79 | 80 | 81 | void loop() { 82 | int t = random(30,110); //fake number range, adjust as you like 83 | int h = random(50,100); 84 | 85 | 86 | Serial.print("uptime: "); 87 | uptime = millis()/1000; 88 | Serial.println(uptime); //prints time since program started 89 | 90 | 91 | client.print(String("GET ") + url + "/?uptime=" + (String) uptime 92 | + "&temperature=" + (String) t + "&humidity=" + (String) h + " HTTP/1.1\r\n" + 93 | "Host: " + host + "\r\n" + 94 | "User-Agent: 14 ESP8266\r\n" + 95 | "Connection: close\r\n\r\n"); 96 | 97 | Serial.println("request sent"); 98 | while (client.connected()) { 99 | String line = client.readStringUntil('\n'); 100 | if (line == "\r") { 101 | Serial.println("headers received"); 102 | break; 103 | } 104 | } 105 | String line = client.readStringUntil('\n'); 106 | if (line.startsWith("{\"state\":\"success\"")) { 107 | Serial.println("esp8266/Arduino CI successfull!"); 108 | } else { 109 | Serial.println("esp8266/Arduino CI has failed"); 110 | } 111 | Serial.println("reply was:"); 112 | Serial.println("=========="); 113 | Serial.println(line); 114 | Serial.println("=========="); 115 | Serial.println("closing connection"); 116 | delay(1000); 117 | 118 | //unlike MQTT, HTTP/HTTPS has to be reconstructed every time a request is processed 119 | // so reconnect after GET request is completed and key/value URL payload is dispatched 120 | if (!client.connect(host, httpsPort)) { 121 | Serial.println("connection failed"); 122 | return; 123 | } 124 | delay(1000); 125 | } 126 | -------------------------------------------------------------------------------- /API_Gateway_Direct/ESP8266-to-API-Key-Secured.ino: -------------------------------------------------------------------------------- 1 | /* 2 | HTTP over TLS (HTTPS) example sketch 3 | This example demonstrates how to use 4 | WiFiClientSecure class to access HTTPS API. 5 | We fetch and display the status of 6 | esp8266/Arduino project continuous integration 7 | build. 8 | Limitations: 9 | only RSA certificates 10 | no support of Perfect Forward Secrecy (PFS) 11 | TLSv1.2 is supported since version 2.4.0-rc1 12 | Created by Ivan Grokhotkov, 2015. 13 | This example is in public domain. 14 | * This example modified by Stephen Borsay for AWS Serverless course on Udemy 15 | * to Connect your device directly to AWS API Gateway 16 | * modified for sending fake data buffer, connect any sensor as desired 17 | * 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | #ifndef STASSID 24 | #define STASSID "" 25 | #define STAPSK "" 26 | #endif 27 | 28 | const char* ssid = STASSID; 29 | const char* password = STAPSK; 30 | const char* host = ".execute-api..amazonaws.com"; //do not include "https://" 31 | String url = ""; 32 | 33 | const char* API_KEY = ""; 34 | 35 | const int httpsPort = 443; 36 | unsigned long uptime; 37 | 38 | // Use web browser to view and copy SHA1 fingerprint of the certificate 39 | //to acquire the thumbprint for this webpage, go to the breadcrumbs in the upper right corner of your browser. 40 | //Then go to Tools-->developer tools-->security-->view certificate-->details(tab)-->thumbprint 41 | //const char fingerprint[] PROGMEM = "98 f8 5e fc 87 65 43 5f 0f c1 1e fe e9 81 c9 9c c2 43 27 4c"; //example thumbprint with proper formatting 42 | 43 | const char fingerprint[] PROGMEM = ""; 44 | 45 | WiFiClientSecure client; 46 | 47 | void setup() { 48 | Serial.begin(115200); 49 | Serial.println(); 50 | Serial.print("connecting to "); 51 | Serial.println(ssid); 52 | WiFi.mode(WIFI_STA); 53 | WiFi.begin(ssid, password); 54 | while (WiFi.status() != WL_CONNECTED) { 55 | delay(500); 56 | Serial.print("."); 57 | } 58 | Serial.println(""); 59 | Serial.println("WiFi connected"); 60 | Serial.println("IP address: "); 61 | Serial.println(WiFi.localIP()); 62 | 63 | // Use WiFiClientSecure class to create TLS connection 64 | 65 | Serial.print("connecting to "); 66 | Serial.println(host); 67 | 68 | Serial.printf("Using fingerprint '%s'\n", fingerprint); 69 | client.setFingerprint(fingerprint); 70 | 71 | if (!client.connect(host, httpsPort)) { 72 | Serial.println("connection failed"); 73 | return; 74 | } 75 | //String url = "/dep1"; 76 | 77 | Serial.print("requesting URL: "); 78 | Serial.println(url); 79 | 80 | } 81 | 82 | 83 | void loop() { 84 | int t = random(30,110); //fake number range, adjust as you like 85 | int h = random(50,100); 86 | 87 | 88 | Serial.print("uptime: "); 89 | uptime = millis()/1000; 90 | Serial.println(uptime); //prints time since program started 91 | 92 | 93 | client.print(String("GET ") + url + "/?uptime=" + (String) uptime 94 | + "&temperature=" + (String) t + "&humidity=" + (String) h + " HTTP/1.1\r\n" + 95 | "Host: " + host + "\r\n" + 96 | "x-api-key: " + API_KEY + "\r\n" + 97 | "User-Agent: 14 ESP8266\r\n" + 98 | "Connection: close\r\n\r\n"); 99 | 100 | Serial.println("request sent"); 101 | while (client.connected()) { 102 | String line = client.readStringUntil('\n'); 103 | if (line == "\r") { 104 | Serial.println("headers received"); 105 | break; 106 | } 107 | } 108 | String line = client.readStringUntil('\n'); 109 | if (line.startsWith("{\"state\":\"success\"")) { 110 | Serial.println("esp8266/Arduino CI successfull!"); 111 | } else { 112 | Serial.println("esp8266/Arduino CI has failed"); 113 | } 114 | Serial.println("reply was:"); 115 | Serial.println("=========="); 116 | Serial.println(line); 117 | Serial.println("=========="); 118 | Serial.println("closing connection"); 119 | delay(1000); 120 | 121 | //unlike MQTT, HTTP/HTTPS has to be reconstructed every time a request is processed 122 | // so reconnect after GET request is completed and key/value URL payload is dispatched 123 | if (!client.connect(host, httpsPort)) { 124 | Serial.println("connection failed"); 125 | return; 126 | } 127 | delay(1000); 128 | } 129 | -------------------------------------------------------------------------------- /API_Gateway_Direct/My-Arduino-lambda-Proxy.js: -------------------------------------------------------------------------------- 1 | var AWS = require('aws-sdk'); 2 | var s3 = new AWS.S3(); 3 | 4 | exports.handler = (event, context, callback) => { 5 | var bucketName = "/"; 6 | var keyName = JSON.stringify(Date.now()); 7 | var content = JSON.stringify(event); //uncomment this statement for testing in lambda 8 | //var content = JSON.stringify(event.queryStringParameters); //uncommnet this statement after integration with API Gateway 9 | //keep only one of the above uncommented! 10 | 11 | 12 | var params = { Bucket: bucketName, Key: keyName, Body: content}; 13 | 14 | s3.putObject(params, function (err, data) { 15 | if (err) 16 | console.log(err); 17 | else 18 | console.log("Successfully saved object to " + bucketName + "/" + keyName 19 | + "and data=" + JSON.stringify(content)); 20 | }); 21 | }; 22 | -------------------------------------------------------------------------------- /API_Gateway_Direct/Visualizations/Chartjs/CORS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "AllowedHeaders": [ 4 | "Authorization" 5 | ], 6 | "AllowedMethods": [ 7 | "GET" 8 | ], 9 | "AllowedOrigins": [ 10 | "*" 11 | ], 12 | "ExposeHeaders": [], 13 | "MaxAgeSeconds": 3000 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /API_Gateway_Direct/Visualizations/Chartjs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Title 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /API_Gateway_Direct/Visualizations/Chartjs/main.js: -------------------------------------------------------------------------------- 1 | var uptime = new Array(); 2 | var humidity = new Array(); 3 | var temperature = new Array(); 4 | 5 | // Start by extracting your folder/key name url from s3 bucket 6 | $.ajax({ 7 | type : "GET", 8 | url : "https://.s3..amazonaws.com/", 9 | dataType : "xml", 10 | success : function(xmlData){ 11 | var url = ""; 12 | keys = xmlData.getElementsByTagName("Key"); 13 | for(i=0; i < keys.length; i++) { 14 | url = keys[i].childNodes[0].nodeValue; 15 | 16 | // Find locate your folder/key string 17 | pos = url.search("/") 18 | if(pos > -1) { 19 | // Detect your folder/key with json file 20 | if(url.replace("/", "") != "") 21 | parseJson(url) 22 | } 23 | } 24 | loadChart(humidity, temperature, uptime ) 25 | }, 26 | error : function(){ 27 | alert("Could not retrieve XML file."); 28 | } 29 | }).always(function() { 30 | console.log(uptime) 31 | }); 32 | 33 | // Parse JSON files 34 | var parseJson = function(url) { 35 | $.ajax({ 36 | type : "GET", 37 | url : "https://.s3..amazonaws.com/" + url, 38 | dataType : "json", 39 | success : function(jsonFile) { 40 | uptime.push(Number(jsonFile.uptime)); 41 | temperature.push(Number(jsonFile.temperature)) 42 | humidity.push(Number(jsonFile.humidity)) 43 | }, 44 | error : function(xhr, status, error) { 45 | console.error("JSON error: " + status); 46 | } 47 | }) 48 | } 49 | -------------------------------------------------------------------------------- /API_Gateway_Direct/Visualizations/Chartjs/visualizer.js: -------------------------------------------------------------------------------- 1 | var loadChart = function(uptime, temperature, humidity) { 2 | var ctx = $('#myChart'); 3 | 4 | var myChart = new Chart(ctx, { 5 | type: 'line', 6 | data: { 7 | labels: uptime, 8 | datasets: [ 9 | { 10 | label: "Temperature", 11 | data: temperature, 12 | fill: false, 13 | borderColor: "rgb(255, 0, 0)", 14 | lineTension: 0.1 15 | }, 16 | { 17 | label: "Humidity", 18 | data: humidity, 19 | fill: false, 20 | borderColor: "rgb(0, 0, 255)", 21 | lineTension: 0.1 22 | } 23 | ] 24 | }, 25 | options: { 26 | title: { 27 | display: true, 28 | text: 'Uptime[1,2,3,4,5,6,7,8]', 29 | position: 'bottom' 30 | } 31 | } 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /API_Gateway_Direct/Visualizations/Highcharts/CORS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "AllowedHeaders": [ 4 | "Authorization" 5 | ], 6 | "AllowedMethods": [ 7 | "GET" 8 | ], 9 | "AllowedOrigins": [ 10 | "*" 11 | ], 12 | "ExposeHeaders": [], 13 | "MaxAgeSeconds": 6000 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /AWSCLI_Test_Payload: -------------------------------------------------------------------------------- 1 | //check your current AWS IoT Core Region 2 | //Place entire command ON ONE LINE! 3 | //aws iot describe-endpoint --endpoint-type iot:Data-ATS 4 | 5 | aws --region us-west-2 iot-data publish --topic "myTopic" --cli-binary-format raw-in-base64-out --payload "{\"uptime\": 123,\"temp\": 44,\"humidity\": 33}" 6 | 7 | 8 | //or if using newer aws2 9 | //Place entire command ON ONE LINE! 10 | 11 | aws2 --region us-west-2 iot-data publish --topic "myTopic" --cli-binary-format raw-in-base64-out --payload "{\"uptime\": 123,\"temp\": 44,\"humidity\": 33}" 12 | 13 | 14 | 15 | //alternate for multiline command on windows CMD 16 | 17 | aws2 --region us-west-2 iot-data publish --topic "myTopic" --cli-binary-format raw-in-base64-out ^ 18 | --payload "{\"uptime\": 123,\"temp\": 44,\"humidity\": 33}" 19 | -------------------------------------------------------------------------------- /Advanced_IoTAnalytics/CORS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "AllowedHeaders": [ 4 | "Authorization" 5 | ], 6 | "AllowedMethods": [ 7 | "GET" 8 | ], 9 | "AllowedOrigins": [ 10 | "*" 11 | ], 12 | "ExposeHeaders": [], 13 | "MaxAgeSeconds": 6000 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /Advanced_IoTAnalytics/extract_csv-data-Lambda.js: -------------------------------------------------------------------------------- 1 | //Rename this file 'index.js' 2 | //this lambda for extracting csv data from your s3 bucket 3 | //.csv to json object conversion for Highcharts 4 | //to browse your bucket schema use https://bucket-name.s3.your-aws-region.amazonaws.com/your-key-name 5 | //keys = dataobjects within s3 bucket 6 | 7 | var AWS = require("aws-sdk"); 8 | 9 | exports.handler = async function (event, context) { 10 | 11 | var s3 = new AWS.S3({ apiVersion: '2006-03-01' }); 12 | var params = { 13 | Bucket: "YOUR-S3-BUCKET-NAME", 14 | MaxKeys: 50 15 | }; 16 | 17 | function csvJSON(csv) { 18 | var lines = csv.split("\n"); 19 | 20 | var result = []; 21 | var headers = lines[0].split(","); 22 | 23 | for (var i = 1; i < lines.length; i++) { 24 | if (lines[i].length > 0) { 25 | var weatherData = lines[i].substring( 26 | lines[i].lastIndexOf("[") + 1, 27 | lines[i].lastIndexOf("]") 28 | ); 29 | weatherData = `${weatherData}`; 30 | lines[i] = lines[i].replace(`${weatherData}`, 'WEATHER_$$$_DATA') 31 | var obj = {}; 32 | var currentline = lines[i].split(","); 33 | 34 | for (var j = 0; j < headers.length; j++) { 35 | headers[j] = headers[j].replace(/"/g, ''); 36 | if (headers[j] == 'weather') { 37 | let splitArr = weatherData.replace(/}/, '').split(','); 38 | let weatherFirstObj = {}; 39 | if (splitArr.length >= 2) { 40 | weatherFirstObj.temperature = splitArr[0].split('=')[1]; 41 | weatherFirstObj.humidity = splitArr[1].split('=')[1]; 42 | } 43 | obj[headers[j]] = weatherFirstObj; 44 | } else { 45 | obj[headers[j]] = currentline[j] ? currentline[j].replace(/"/g, '') : ''; 46 | } 47 | } 48 | result.push(obj); 49 | } 50 | 51 | } 52 | console.log('JSON.stringify(result);',JSON.stringify(result)) 53 | return result; 54 | 55 | } 56 | 57 | 58 | return new Promise((resolve,reject)=>{ 59 | s3.listObjects(params, (err, objects) => { 60 | if (err) 61 | return console.log(err); 62 | if (objects && objects.Contents && objects.Contents.length > 0) { 63 | let contents = objects.Contents; 64 | contents.sort(function (a, b) { 65 | return new Date(b.LastModified) - new Date(a.LastModified); 66 | }); 67 | 68 | let latestCsvData = contents[0]; 69 | var params1 = { 70 | Bucket: "YOUR-S3-BUCKET-NAME", 71 | Key: latestCsvData.Key 72 | }; 73 | s3.getObject(params1, (err, data) => { 74 | if (err) { 75 | console.log(err); 76 | reject(false); 77 | } else { 78 | try { 79 | var dataArray = data.Body.toString('utf-8'); 80 | resolve(csvJSON(dataArray)); 81 | } catch (error) { 82 | console.log(error); 83 | reject(false); 84 | } 85 | } 86 | }) 87 | } 88 | }) 89 | }); 90 | 91 | 92 | }; 93 | -------------------------------------------------------------------------------- /Advanced_IoTAnalytics/test_payload.json: -------------------------------------------------------------------------------- 1 | //moab, ut 2 | 3 | [ 4 | { 5 | "uptime": 100, 6 | "intemp": 77, 7 | "inhumid": 66, 8 | "lat": 38.5743966, 9 | "long": -109.5689282 10 | 11 | } 12 | ] 13 | 14 | //tuscon, az 15 | 16 | [ 17 | { 18 | "uptime": 110, 19 | "intemp": 88, 20 | "inhumid": 99, 21 | "lat": 32.1558328, 22 | "long": -111.0238918 23 | } 24 | ] 25 | 26 | //chicago 27 | 28 | [ 29 | { 30 | "uptime": 120, 31 | "intemp": 85, 32 | "inhumid": 95, 33 | "lat": 41.881832, 34 | "long": -87.623177 35 | } 36 | ] 37 | 38 | 39 | //stevenson 40 | 41 | [ 42 | { 43 | "uptime": 120, 44 | "intemp": 88, 45 | "inhumid": 99, 46 | "lat": 45.6944496, 47 | "long": -121.9115935 48 | } 49 | ] 50 | 51 | //can use aws or aws continget on your AWS CLI installation edition 52 | aws2 --region us-east-2 lambda add-permission --function-name weathergpS413 --statement-id 12345 --principal iotanalytics.amazonaws.com --action lambda:InvokeFunction 53 | aws2 lambda add-permission --function-name weatherGPS420 --statement-id 54321 --principal iotanalytics.amazonaws.com --action lambda:InvokeFunction 54 | -------------------------------------------------------------------------------- /Advanced_IoTAnalytics/transformLambda.js: -------------------------------------------------------------------------------- 1 | //call this file 'index.js' 2 | //AWS permission CLI directions at botton of page 3 | //Payloads to test this Lambda with are in this github subdirectory 4 | 5 | var weather = require("weather-js"); //https://www.npmjs.com/package/weather-js 6 | var cities = require('cities'); //https://www.npmjs.com/package/cities 7 | var AWS = require('aws-sdk'); 8 | 9 | exports.handler = async function(event, context) { 10 | 11 | let promiseData = []; 12 | 13 | let weatherPromise = function(data){ 14 | return new Promise((resolve,reject)=>{ 15 | weather.find({search: `${data.State} ${data.City}`, degreeType: 'F'}, function(err, result) { 16 | if(err) console.log('error weather',err); 17 | 18 | let weatherTempArr = []; 19 | if(result) { 20 | result.forEach(item=>{ 21 | console.log(item.current.temperature); 22 | weatherTempArr.push({ 23 | temperature: item.current.temperature, 24 | humidity:item.current.humidity 25 | }) 26 | }); 27 | } 28 | data.weather = weatherTempArr; 29 | resolve(data); 30 | }); 31 | }) 32 | } 33 | 34 | event.forEach(message => { 35 | // do some stuff to `message` 36 | //use incoming lattitude nd longitude from event object to get city and state 37 | const obj= cities.gps_lookup(message.lat, message.long); 38 | 39 | //get ISO8601 date formate. ntively supported in browser JS 40 | var d = new Date(); 41 | var n = d.toISOString(); //move timestamping function to local scope to prevent 'warm start' issues, and memory heap TSR issue 42 | 43 | /******************* get current weather by using city and state fromm cities.js *******************/ 44 | let data = Object.assign({},message,{City:obj.city, State:obj.state, Time:n}); 45 | promiseData.push(weatherPromise(data)) 46 | /******************* end *******************/ 47 | 48 | }); //end for each 49 | 50 | const responses = await Promise.all(promiseData); 51 | return responses; 52 | 53 | }; 54 | 55 | //Lambda pernissions from the AWS CLI, 'aws' or 'aws2' contingent on your AWS CLI edition 56 | // reference(currently Page 45, 105) https://docs.aws.amazon.com/iotanalytics/latest/userguide/analytics-ug.pdf 57 | //example 1 58 | //aws lambda add-permission --function-name --region --statement-id --principal iotanalytics.amazonaws.com --action lambda:InvokeFunction 59 | //example2 60 | //aws2 lambda add-permission --function-name YOUR-LAMBDA-FUNCTION --statement-id 34545 --principal iotanalytics.amazonaws.com --action lambda:InvokeFunction 61 | //example3 62 | //aws --region us-east-2 lambda add-permission --function-name YOUR-LAMBDA-FUNCTION --statement-id 12345 --principal iotanalytics.amazonaws.com --action lambda:InvokeFunction 63 | -------------------------------------------------------------------------------- /Basic_IoT_Analytics/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 60 | 61 | 62 |
63 | 64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /Basic_IoT_Analytics/oldSagemaker_Py2.7: -------------------------------------------------------------------------------- 1 | import boto3 2 | import pandas as pd 3 | from matplotlib import pyplot as plt 4 | 5 | # create IoT Analytics client 6 | client = boto3.client('iotanalytics') 7 | 8 | #after running the code portion above run the code below with your own dataset 9 | 10 | 11 | dataset = "YOUR_DATASET_HERE" 12 | dataset_url = client.get_dataset_content(datasetName = dataset)['entries'][0]['dataURI'] 13 | 14 | # start working with the data 15 | 16 | df = pd.read_csv(dataset_url) 17 | df.timestamp = pd.to_datetime(pd.to_numeric(df.timestamp), unit='ms') 18 | df.set_index(df.timestamp, inplace=True) 19 | df.sort_values('timestamp', inplace=True) 20 | 21 | fig, ax = plt.subplots() 22 | df.temperature.plot(legend=True) 23 | df.humidity.plot(legend=True) 24 | plt.show() 25 | 26 | print('Average Humidity: ', df.humidity.mean()) 27 | print('Number of samples: ', len(df)) 28 | 29 | print('Average temperature: ', df.temperature.mean()) 30 | print('Number of samples: ', len(df)) 31 | -------------------------------------------------------------------------------- /Basic_IoT_Analytics/old_index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 69 | 70 | 71 | Your own IoT AWS Project 72 |
73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Basic_IoT_Analytics/sagemaker.py: -------------------------------------------------------------------------------- 1 | #Using 'conda_chainer_p36' or 'conda_pytorch_p38' 2 | 3 | import boto3 4 | import pandas as pd 5 | from matplotlib import pyplot as plt 6 | 7 | # create IoT Analytics client 8 | client = boto3.client('iotanalytics') 9 | 10 | #after running the code portion above run the code below with your own dataset 11 | 12 | dataset = "YOUR_DATASET_HERE" # Example: dataset = "analytics615_dataset" 13 | dataset_url = client.get_dataset_content(datasetName = dataset)['entries'][0]['dataURI'] 14 | 15 | # start working with the data 16 | 17 | df = pd.read_csv(dataset_url) 18 | df.serversidetimestamp = pd.to_datetime(pd.to_numeric(df.serversidetimestamp), unit='ms') 19 | df.set_index(df.serversidetimestamp, inplace=True) 20 | #df.sort_values('serversidetimestamp', inplace=True) 21 | 22 | fig, ax = plt.subplots() 23 | df.temperature.plot(legend=True) 24 | df.humidity.plot(legend=True) 25 | plt.show() 26 | 27 | print('Average Humidity: ', df.humidity.mean()) 28 | print('Number of samples: ', len(df)) 29 | 30 | print('Average temperature: ', df.temperature.mean()) 31 | print('Number of samples: ', len(df)) 32 | -------------------------------------------------------------------------------- /ESP32toAWS-No_Formatting_required.ino: -------------------------------------------------------------------------------- 1 | /* ESP32 AWS IoT 2 | * 3 | * Simplest possible example (that I could come up with) of using an ESP32 with AWS IoT. 4 | * 5 | * Author: Anthony Elder 6 | * License: Apache License v2 7 | * Sketch Modified by Stephen Borsay for www.udemy.com and AWS IoT Live Workshops 8 | * https://github.com/sborsay 9 | * Add in Char buffer utilizing sprintf to dispatch JSON data to AWS IoT Core 10 | *simplified certificate formatting using EOF and progmem 11 | * Use and replace your own SID, PW, AWS Account Endpoint, Client cert, private cert, x.509 CA root Cert 12 | */ 13 | #include 14 | #include // install with Library Manager, I used v2.6.0 15 | 16 | const char* ssid = "YOUR NETWORK NAME"; 17 | const char* password = "YOUR NETWORK PASSWORD"; 18 | 19 | const char* awsEndpoint = "YOUR-AWS-IOT-ENDPOINT"; //AWS IoT Core--> Settings (Device data endpoint) 20 | 21 | // xxxxxxxxxx-certificate.pem.crt 22 | static const char certificate_pem_crt[] PROGMEM = R"KEY( 23 | -----BEGIN CERTIFICATE----- 24 | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXAoccwSpJEkwDQYJKoZIhvcNAQEL 25 | BQAwTTFLMEkGA1UECwxCQW1hem9uIFdlYiBTZXJ2aWNlcyBPPUFtYXpvbi5jb20g 26 | SW5jLiBMPVNlYXR0bGUgU1Q9V2FzaGluZ3RvbiBDPVVTMB4XDTIxMDYyMzAzNDk1 27 | OFoXDTQ5MTIzMTIzNTk1OVowHjEcMBoGA1UEAwwTQVdTIElvVCBDZXJ0aWZpY2F0 28 | ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMlywFsajU0WY53cA2Dv 29 | BdToiQzjBKG/6FKjIYB6D47nn1pvp03xkCewoF09uaKIHam2raL4XV71eeGFvFHj 30 | cn49cfaYPfIsi2Keoxio+H6W+MJZHNt7XE4NiJydqAv+BjC6/aBPRrcP7X+HmDVV 31 | mRbn8uLBnJKRlh6wK1/91q+2e9bpnoNz6IjyUEssQpB9Qtr99FSNl+PNloJr1Ki4 32 | vs4IBJbwNv3kdblHVqd1V7GgYePbx+LqVQzf3IMecNqP1f8WYRMRuQ6RR9dYGFHU 33 | cwmodbigKYd2IGcEOEfU0NYFlXJJ/7a8Nq8KKfDorZAQwJRkr8gOZR9TkpymiYxu 34 | 2SUCAwEAAaNgMF4wHwYDVR0jBBgwFoAUk5u9teDtHdsYtv8EPE/ZVGiubEYwHQYD 35 | VR0OBBYEFFefBYP1bu1wgutG7/0Q3pSbYIYTMAwGA1UdEwEB/wQCMAAwDgYDVR0P 36 | AQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4IBAQCYFcP1pz4el9vBFO5AmTy4MtzM 37 | wpQRyLC/rZpGkBmMxwyAwuweHYnMD2n3jSBcNNoZ69K3lVTpmlw26421P6qtf+Sf 38 | b9e1vZzTtN2izGGNrR93y/3AxA0fCmkD0JNbfomd77uGnyiOOhrX/2b78Kb59vm4 39 | oSjgR4/NU4dM1dJ8isMOaNQxGC1PvOYjFLJlOAEg5VMJUGgfRrqD5d4LVp9k26ok 40 | ArYEEPnFK6wxXl273g+ZS3dED66/Wny6YYZqdGbyuL59DGNnlpjNVkOAYeh/9MZF 41 | TXi8gPMGeExHgXq5oxbkekl58/pm4dkX8Foo0mY8Vfdq5kMqKhtlKQBtQLUp 42 | -----END CERTIFICATE----- 43 | )KEY"; 44 | 45 | // xxxxxxxxxx-private.pem.key 46 | static const char private_pem_key[] PROGMEM = R"KEY( 47 | -----BEGIN RSA PRIVATE KEY----- 48 | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXoUqMhgHoPjuefWm+n 49 | TfGQJ7CgXT25oogdqbatovhdXvV54YW8UeNyfj1x9pg98iyLYp6jGKj4fpb4wlkc 50 | 23tcTg2InJ2oC/4GMLr9oE9Gtw/tf4eYNVWZFufy4sGckpGWHrArX/3Wr7Z71ume 51 | g3PoiPJQSyxCkH1C2v30VI2X482WgmvUqLi+zggElvA2/eR1uUdWp3VXsaBh49vH 52 | 4upVDN/cgx5w2o/V/xZhExG5DpFH11gYUdRzCah1uKAph3YgZwQ4R9TQ1gWVckn/ 53 | trw2rwop8OitkBDAlGSvyA5lH1OSnKaJjG7ZJQIDAQABAoIBAAakewVGBdzB3T0K 54 | US40E3wmwsYjAjcXLeDzshobbEHpD08bGWgvi/JTF6abb3CVjmzXMjiKegG0lHVE 55 | RKZqmo7hFc3szTYcE+iHlJcukysRbVhzOcle8vc76QJJDI6ArNGUiOJtWsaUht9K 56 | qFEx5l9j/JVPjwsiM9IFOxjqNNcMXWAMgVvO1PCNxzI5YzUJADNRjccrFxdzl1b7 57 | sbL3TmUnx/sOCQCg2e8UwNfPj8C4vcE/04IO2ew9zfkNZFy2tru3RXJaB+r5v+Mg 58 | he26f9HuYbcAED4Z6/0zTS0EM7BwN7GTaUUaGezDw0ITGXCvqA8SJul7mCYQOdK1 59 | fKWiJiECgYEA7wIhzfY83hewYHb6DJTIaA3HyxgdiCxXyWZmKtaPT/0flaH2k273 60 | wtTyQfiBthpjKH64ksrSghhIJl0BMDgTcpiaSvVR7EL7deYrGqo/YnzX538oinD9 61 | t2H2TfqFepTkac+QxEZ746ybj9z8EqOMbXgNPa6FeSnJnA9pxObcPpkCgYEA18UJ 62 | /NHmwJgHU7GJHLNM7yO4GrKuGwZlAQwGh75gtm6P7MjnoCmnzgcynep9sW5t2zey 63 | dW8AudSFcVakIi1Q+kWrc92akglYHeRVQwtlfug+pnbbk3V1cBzzGQ63YgZh9FZr 64 | qCCZhjOhqDG8F7EJY7pY3omKn7WGL4pbhstjAm0CgYAbrwyJVbcxJl9InR9Ta7xW 65 | yRnWPWHWTwSQEGtPFPEem7wX0d3Er/rEt3OkDou/swi/PQZWAmYlqXhZ8TXdBvHB 66 | uUlN22J00kFcI5/kg8m5t6ouZz0j4/iPUCp+V8E0NKDMXL1w7pUVBv4xyK/t3MG8 67 | QEaQWXGeWie/Cs3+f5sNKQKBgQCQ72QUFRLBT92sFFcblj0ZbY7fMCLPOG5kU6WX 68 | TQQ9xuqajSE5boGvXRpdBQRFSP42AKW5SETejqjMRvydkH8SffX7MGIBspEkExpK 69 | nL8ijfJ3cuNvm7i1BF0u+bmo+MyXie1q0+sMQGZYSoAkEeFSwfusEAuz2AU4reFp 70 | G/l3yQKBgEMGm87PrO0rcNlcL99pHxT5QjydL9FWvq5eg4dC3yNJcqvd620eXt83 71 | mYcLcO5Q+SWLNm/NjcQCIMZ/cuS1knTDZV3JIT44tCn4Q+Z6OFvy+KNFZOaQc3Ed 72 | Cmr5ttndjNAEfVOUKPN+8wXx4o8Fbd9dkhwggvBaMQhQjaSzzMJs 73 | -----END RSA PRIVATE KEY----- 74 | )KEY"; 75 | 76 | /* root CA can be downloaded in: 77 | https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem 78 | fungible between regions, I dont care if you use mine below or paste in your own. 79 | */ 80 | static const char rootCA[] PROGMEM = R"EOF( 81 | -----BEGIN CERTIFICATE----- 82 | MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF 83 | ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 84 | b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL 85 | MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv 86 | b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj 87 | ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM 88 | 9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw 89 | IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 90 | VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L 91 | 93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm 92 | jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC 93 | AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA 94 | A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI 95 | U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs 96 | N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv 97 | o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU 98 | 5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy 99 | rqXRfboQnoZsG4q5WTP468SQvvG5 100 | -----END CERTIFICATE----- 101 | )EOF"; 102 | 103 | 104 | WiFiClientSecure wiFiClient; 105 | void msgReceived(char* topic, byte* payload, unsigned int len); 106 | PubSubClient pubSubClient(awsEndpoint, 8883, msgReceived, wiFiClient); 107 | 108 | void setup() { 109 | Serial.begin(115200); delay(50); Serial.println(); 110 | Serial.println("ESP32 AWS IoT Example"); 111 | Serial.printf("SDK version: %s\n", ESP.getSdkVersion()); 112 | 113 | Serial.print("Connecting to "); Serial.print(ssid); 114 | WiFi.begin(ssid, password); 115 | WiFi.waitForConnectResult(); 116 | Serial.print(", WiFi connected, IP address: "); Serial.println(WiFi.localIP()); 117 | 118 | wiFiClient.setCACert(rootCA); 119 | wiFiClient.setCertificate(certificate_pem_crt); 120 | wiFiClient.setPrivateKey(private_pem_key); 121 | } 122 | 123 | unsigned long lastPublish; 124 | int msgCount; 125 | 126 | void loop() { 127 | 128 | pubSubCheckConnect(); 129 | 130 | //If you need to increase buffer size, you need to change MQTT_MAX_PACKET_SIZE in PubSubClient.h 131 | char fakeData[128]; 132 | 133 | float var1 = random(55,77); //fake number range, adjust as you like 134 | float var2 = random(77,99); 135 | sprintf(fakeData, "{\"uptime\":%lu,\"temp\":%f,\"humid\":%f}", millis() / 1000, var1, var2); 136 | 137 | 138 | if (millis() - lastPublish > 10000) { 139 | boolean rc = pubSubClient.publish("outTopic", fakeData); 140 | Serial.print("Published, rc="); Serial.print( (rc ? "OK: " : "FAILED: ") ); 141 | Serial.println(fakeData); 142 | lastPublish = millis(); 143 | 144 | 145 | } 146 | } 147 | 148 | void msgReceived(char* topic, byte* payload, unsigned int length) { 149 | Serial.print("Message received on "); Serial.print(topic); Serial.print(": "); 150 | for (int i = 0; i < length; i++) { 151 | Serial.print((char)payload[i]); 152 | } 153 | Serial.println(); 154 | } 155 | 156 | void pubSubCheckConnect() { 157 | if ( ! pubSubClient.connected()) { 158 | Serial.print("PubSubClient connecting to: "); Serial.print(awsEndpoint); 159 | while ( ! pubSubClient.connected()) { 160 | Serial.print("."); 161 | pubSubClient.connect("ESPthingXXXX"); 162 | delay(1000); 163 | } 164 | Serial.println(" connected"); 165 | pubSubClient.subscribe("inTopic"); 166 | } 167 | pubSubClient.loop(); 168 | } 169 | -------------------------------------------------------------------------------- /ESP_No_Cert_Formatting/ESP32toAWS-No_Formatting_required.ino: -------------------------------------------------------------------------------- 1 | /* ESP32 AWS IoT 2 | * 3 | * Simplest possible example (that I could come up with) of using an ESP32 with AWS IoT. 4 | * 5 | * Author: Anthony Elder 6 | * License: Apache License v2 7 | * Sketch Modified by Stephen Borsay for www.udemy.com and AWS IoT Live Workshops 8 | * https://github.com/sborsay 9 | * Add in Char buffer utilizing sprintf to dispatch JSON data to AWS IoT Core 10 | * Use and replace your own SID, PW, AWS Account Endpoint, Client cert, private cert, x.509 CA root Cert 11 | */ 12 | #include 13 | #include // install with Library Manager, I used v2.6.0 14 | 15 | const char* ssid = "YOUR NETWORK NAME"; 16 | const char* password = "YOUR NETWORK PASSWORD"; 17 | 18 | const char* awsEndpoint = "YOUR-AWS-IOT-ENDPOINT"; //AWS IoT Core--> Settings (Device data endpoint) 19 | 20 | // xxxxxxxxxx-certificate.pem.crt 21 | static const char certificate_pem_crt[] PROGMEM = R"KEY( 22 | -----BEGIN CERTIFICATE----- 23 | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXAoccwSpJEkwDQYJKoZIhvcNAQEL 24 | BQAwTTFLMEkGA1UECwxCQW1hem9uIFdlYiBTZXJ2aWNlcyBPPUFtYXpvbi5jb20g 25 | SW5jLiBMPVNlYXR0bGUgU1Q9V2FzaGluZ3RvbiBDPVVTMB4XDTIxMDYyMzAzNDk1 26 | OFoXDTQ5MTIzMTIzNTk1OVowHjEcMBoGA1UEAwwTQVdTIElvVCBDZXJ0aWZpY2F0 27 | ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMlywFsajU0WY53cA2Dv 28 | BdToiQzjBKG/6FKjIYB6D47nn1pvp03xkCewoF09uaKIHam2raL4XV71eeGFvFHj 29 | cn49cfaYPfIsi2Keoxio+H6W+MJZHNt7XE4NiJydqAv+BjC6/aBPRrcP7X+HmDVV 30 | mRbn8uLBnJKRlh6wK1/91q+2e9bpnoNz6IjyUEssQpB9Qtr99FSNl+PNloJr1Ki4 31 | vs4IBJbwNv3kdblHVqd1V7GgYePbx+LqVQzf3IMecNqP1f8WYRMRuQ6RR9dYGFHU 32 | cwmodbigKYd2IGcEOEfU0NYFlXJJ/7a8Nq8KKfDorZAQwJRkr8gOZR9TkpymiYxu 33 | 2SUCAwEAAaNgMF4wHwYDVR0jBBgwFoAUk5u9teDtHdsYtv8EPE/ZVGiubEYwHQYD 34 | VR0OBBYEFFefBYP1bu1wgutG7/0Q3pSbYIYTMAwGA1UdEwEB/wQCMAAwDgYDVR0P 35 | AQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4IBAQCYFcP1pz4el9vBFO5AmTy4MtzM 36 | wpQRyLC/rZpGkBmMxwyAwuweHYnMD2n3jSBcNNoZ69K3lVTpmlw26421P6qtf+Sf 37 | b9e1vZzTtN2izGGNrR93y/3AxA0fCmkD0JNbfomd77uGnyiOOhrX/2b78Kb59vm4 38 | oSjgR4/NU4dM1dJ8isMOaNQxGC1PvOYjFLJlOAEg5VMJUGgfRrqD5d4LVp9k26ok 39 | ArYEEPnFK6wxXl273g+ZS3dED66/Wny6YYZqdGbyuL59DGNnlpjNVkOAYeh/9MZF 40 | TXi8gPMGeExHgXq5oxbkekl58/pm4dkX8Foo0mY8Vfdq5kMqKhtlKQBtQLUp 41 | -----END CERTIFICATE----- 42 | )KEY"; 43 | 44 | // xxxxxxxxxx-private.pem.key 45 | static const char private_pem_key[] PROGMEM = R"KEY( 46 | -----BEGIN RSA PRIVATE KEY----- 47 | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXoUqMhgHoPjuefWm+n 48 | TfGQJ7CgXT25oogdqbatovhdXvV54YW8UeNyfj1x9pg98iyLYp6jGKj4fpb4wlkc 49 | 23tcTg2InJ2oC/4GMLr9oE9Gtw/tf4eYNVWZFufy4sGckpGWHrArX/3Wr7Z71ume 50 | g3PoiPJQSyxCkH1C2v30VI2X482WgmvUqLi+zggElvA2/eR1uUdWp3VXsaBh49vH 51 | 4upVDN/cgx5w2o/V/xZhExG5DpFH11gYUdRzCah1uKAph3YgZwQ4R9TQ1gWVckn/ 52 | trw2rwop8OitkBDAlGSvyA5lH1OSnKaJjG7ZJQIDAQABAoIBAAakewVGBdzB3T0K 53 | US40E3wmwsYjAjcXLeDzshobbEHpD08bGWgvi/JTF6abb3CVjmzXMjiKegG0lHVE 54 | RKZqmo7hFc3szTYcE+iHlJcukysRbVhzOcle8vc76QJJDI6ArNGUiOJtWsaUht9K 55 | qFEx5l9j/JVPjwsiM9IFOxjqNNcMXWAMgVvO1PCNxzI5YzUJADNRjccrFxdzl1b7 56 | sbL3TmUnx/sOCQCg2e8UwNfPj8C4vcE/04IO2ew9zfkNZFy2tru3RXJaB+r5v+Mg 57 | he26f9HuYbcAED4Z6/0zTS0EM7BwN7GTaUUaGezDw0ITGXCvqA8SJul7mCYQOdK1 58 | fKWiJiECgYEA7wIhzfY83hewYHb6DJTIaA3HyxgdiCxXyWZmKtaPT/0flaH2k273 59 | wtTyQfiBthpjKH64ksrSghhIJl0BMDgTcpiaSvVR7EL7deYrGqo/YnzX538oinD9 60 | t2H2TfqFepTkac+QxEZ746ybj9z8EqOMbXgNPa6FeSnJnA9pxObcPpkCgYEA18UJ 61 | /NHmwJgHU7GJHLNM7yO4GrKuGwZlAQwGh75gtm6P7MjnoCmnzgcynep9sW5t2zey 62 | dW8AudSFcVakIi1Q+kWrc92akglYHeRVQwtlfug+pnbbk3V1cBzzGQ63YgZh9FZr 63 | qCCZhjOhqDG8F7EJY7pY3omKn7WGL4pbhstjAm0CgYAbrwyJVbcxJl9InR9Ta7xW 64 | yRnWPWHWTwSQEGtPFPEem7wX0d3Er/rEt3OkDou/swi/PQZWAmYlqXhZ8TXdBvHB 65 | uUlN22J00kFcI5/kg8m5t6ouZz0j4/iPUCp+V8E0NKDMXL1w7pUVBv4xyK/t3MG8 66 | QEaQWXGeWie/Cs3+f5sNKQKBgQCQ72QUFRLBT92sFFcblj0ZbY7fMCLPOG5kU6WX 67 | TQQ9xuqajSE5boGvXRpdBQRFSP42AKW5SETejqjMRvydkH8SffX7MGIBspEkExpK 68 | nL8ijfJ3cuNvm7i1BF0u+bmo+MyXie1q0+sMQGZYSoAkEeFSwfusEAuz2AU4reFp 69 | G/l3yQKBgEMGm87PrO0rcNlcL99pHxT5QjydL9FWvq5eg4dC3yNJcqvd620eXt83 70 | mYcLcO5Q+SWLNm/NjcQCIMZ/cuS1knTDZV3JIT44tCn4Q+Z6OFvy+KNFZOaQc3Ed 71 | Cmr5ttndjNAEfVOUKPN+8wXx4o8Fbd9dkhwggvBaMQhQjaSzzMJs 72 | -----END RSA PRIVATE KEY----- 73 | )KEY"; 74 | 75 | /* root CA found at: 76 | https://www.amazontrust.com/repository/AmazonRootCA1.pem 77 | fungible between regions, I dont care if you use mine below or paste in your own. 78 | */ 79 | static const char rootCA[] PROGMEM = R"EOF( 80 | -----BEGIN CERTIFICATE----- 81 | MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF 82 | ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 83 | b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL 84 | MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv 85 | b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj 86 | ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM 87 | 9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw 88 | IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 89 | VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L 90 | 93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm 91 | jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC 92 | AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA 93 | A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI 94 | U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs 95 | N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv 96 | o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU 97 | 5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy 98 | rqXRfboQnoZsG4q5WTP468SQvvG5 99 | -----END CERTIFICATE----- 100 | )EOF"; 101 | 102 | 103 | WiFiClientSecure wiFiClient; 104 | void msgReceived(char* topic, byte* payload, unsigned int len); 105 | PubSubClient pubSubClient(awsEndpoint, 8883, msgReceived, wiFiClient); 106 | 107 | void setup() { 108 | Serial.begin(115200); delay(50); Serial.println(); 109 | Serial.println("ESP32 AWS IoT Example"); 110 | Serial.printf("SDK version: %s\n", ESP.getSdkVersion()); 111 | 112 | Serial.print("Connecting to "); Serial.print(ssid); 113 | WiFi.begin(ssid, password); 114 | WiFi.waitForConnectResult(); 115 | Serial.print(", WiFi connected, IP address: "); Serial.println(WiFi.localIP()); 116 | 117 | wiFiClient.setCACert(rootCA); 118 | wiFiClient.setCertificate(certificate_pem_crt); 119 | wiFiClient.setPrivateKey(private_pem_key); 120 | } 121 | 122 | unsigned long lastPublish; 123 | int msgCount; 124 | 125 | void loop() { 126 | 127 | pubSubCheckConnect(); 128 | 129 | //If you need to increase buffer size, you need to change MQTT_MAX_PACKET_SIZE in PubSubClient.h 130 | char fakeData[128]; 131 | 132 | float var1 = random(55,77); //fake number range, adjust as you like 133 | float var2 = random(77,99); 134 | sprintf(fakeData, "{\"uptime\":%lu,\"temp\":%f,\"humid\":%f}", millis() / 1000, var1, var2); 135 | 136 | 137 | if (millis() - lastPublish > 10000) { 138 | boolean rc = pubSubClient.publish("outTopic", fakeData); 139 | Serial.print("Published, rc="); Serial.print( (rc ? "OK: " : "FAILED: ") ); 140 | Serial.println(fakeData); 141 | lastPublish = millis(); 142 | 143 | 144 | } 145 | } 146 | 147 | void msgReceived(char* topic, byte* payload, unsigned int length) { 148 | Serial.print("Message received on "); Serial.print(topic); Serial.print(": "); 149 | for (int i = 0; i < length; i++) { 150 | Serial.print((char)payload[i]); 151 | } 152 | Serial.println(); 153 | } 154 | 155 | void pubSubCheckConnect() { 156 | if ( ! pubSubClient.connected()) { 157 | Serial.print("PubSubClient connecting to: "); Serial.print(awsEndpoint); 158 | while ( ! pubSubClient.connected()) { 159 | Serial.print("."); 160 | pubSubClient.connect("ESPthingXXXX"); 161 | delay(1000); 162 | } 163 | Serial.println(" connected"); 164 | pubSubClient.subscribe("inTopic"); 165 | } 166 | pubSubClient.loop(); 167 | } 168 | -------------------------------------------------------------------------------- /ESP_No_Cert_Formatting/ESP8266_version_3+_by_ESP8266_Community/README.md: -------------------------------------------------------------------------------- 1 | ---------------------------- 2 | 3 | ## Compile this only if using ESP8266 version 3+, not backwards comparable 4 | 5 | # Tools--> Board--> Board Manager-->ESP8266 version 3+ by ESP8266 Community 6 | 7 | ## Older ESP8266 sketch is not forward compitable 8 | 9 | -------------------------------- 10 | -------------------------------------------------------------------------------- /ESP_No_Cert_Formatting/README.md: -------------------------------------------------------------------------------- 1 | In the Arduino IDE: 2 | 3 | File-->Preferences-->Additional Board Manager URL's --> 4 | ENTER: 5 | https://dl.espressif.com/dl/package_esp32_index.json, http://arduino.esp8266.com/stable/package_esp8266com_index.json 6 | 7 | This will allow you to find the Board Manager Package required. 8 | 9 | ---------------------------- 10 | 11 | ## Compile this only if using ESP8266 Board Manager version below 3.0, use the other ESP8266 sketch if version 3+ or above 12 | 13 | ### Tools--> Board--> Board Manager-->ESP8266 by ESP8266 Community 14 | 15 | #### Board Manager versions are neither forward nor backwards compatable with new BEARSSL Certificate and anchor requirments 16 | -------------------------------- 17 | -------------------------------------------------------------------------------- /GoogleCharts_CSV.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 69 | 70 | 71 | Your own IoT AWS Project 72 |
73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Guitar_refactored/Attach2LambdaPolicy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": { 4 | "Effect": "Allow", 5 | "Action": "dynamodb:PutItem", 6 | "Resource": "arn:aws:dynamodb:::table/" 7 | } 8 | } 9 | 10 | -------------------------------------------------------------------------------- /Guitar_refactored/CORS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "AllowedHeaders": [ 4 | "Authorization" 5 | ], 6 | "AllowedMethods": [ 7 | "GET" 8 | ], 9 | "AllowedOrigins": [ 10 | "*" 11 | ], 12 | "ExposeHeaders": [], 13 | "MaxAgeSeconds": 6000 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /Guitar_refactored/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Home Monitoring App 9 | 10 |
14 |
15 |
16 |

Temperature & Humidity Dashboard

17 |

Guitar Storage Room

18 |

19 |
20 |
21 |
22 |
23 | High  24 |
25 |
26 | (n/a) 27 |
28 |
29 |
30 |
31 | Low  32 |
33 |
34 | (n/a) 35 |
36 |
37 |
38 |
39 |

40 |
41 |
42 |
43 |
44 | High  45 |
46 |
47 | (n/a) 48 |
49 |
50 |
51 |
52 | Low  53 |
54 |
55 | (n/a) 56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |

5 minute feed from home sensors for the past 24 hours.

64 |
65 |
66 |

Copyright © Devan Sabaratnam - Blaze Business Software Pty Ltd

67 |
68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /Guitar_refactored/index.js: -------------------------------------------------------------------------------- 1 | //new lambda for data enhancemant uptime to ISO8601 transformm for Devan Sabaratnam's Guitar Project 2 | //https://hackernoon.com/building-an-iot-dashboard-using-the-onion-omega-and-amazon-aws-a3520f850c9 3 | //Lambda added for course on serverless IoT on AWS at Udemy.com 4 | //call this Lmabda fnction index.js in Node for the aws-sdk 5 | 6 | // Load the SDK for JavaScript 7 | const AWS = require('aws-sdk'); 8 | // Set the Region 9 | const docClient = new AWS.DynamoDB.DocumentClient({region: ''}); 10 | 11 | exports.handler = function(event, context, callback) { 12 | 13 | //let myDate = new Date(); 14 | let ISO_Date = new Date().toISOString(); //converted to a single line for the pedantics 15 | //moved time inside of the function to prevent 16 | //warm starts from reusuing old timestamp 17 | 18 | var params = { 19 | 20 | Item: { 21 | // PARTITION_KEY: {'S': 'id'}, 22 | // SORT_KEY: {'N': 'timestamp'}, 23 | 24 | id: "outTopic", 25 | timestamp: Date.now(), 26 | 27 | payload:{ 28 | 29 | "datetime": ISO_Date, 30 | "temperature": event.temperature, 31 | "humidity": event.humidity 32 | 33 | }, 34 | 35 | }, 36 | 37 | TableName: 'myDDBTable' 38 | 39 | }; 40 | 41 | 42 | docClient.put(params, function(err, data) { 43 | if (err) callback(err, err.stack); // an error occurred 44 | else callback(null,data); // successful response 45 | } 46 | ); 47 | }; 48 | -------------------------------------------------------------------------------- /Guitar_refactored/payload.json: -------------------------------------------------------------------------------- 1 | { 2 | "uptime": 22, 3 | "temperature": 77, 4 | "humidity": 88 5 | } 6 | -------------------------------------------------------------------------------- /Guitar_refactored/refresh.js: -------------------------------------------------------------------------------- 1 | //from https://hackernoon.com/building-an-iot-dashboard-using-the-onion-omega-and-amazon-aws-a3520f850c9 2 | // device payload example 3 | /* 4 | { 5 | "datetime": "2020-02-21T02:10:12Z", //convert unix Epoch to ISO8601 string. 6 | "temperature": 26.1, 7 | "humidity": 33.29 8 | } 9 | 10 | 11 | { 12 | datetime: logDate.toISOString(), 13 | temperature: parseFloat(dataArray[1]), 14 | humidity: parseFloat(dataArray[0]) 15 | } 16 | 17 | */ 18 | 19 | 20 | // Initialize the Amazon Cognito credentials provider 21 | AWS.config.region = ''; // Region 22 | AWS.config.credentials = new AWS.CognitoIdentityCredentials({ 23 | IdentityPoolId: 'us-east-1:2e1bdxxx-cxxx-4xxx-axxx-182xxxxx769', 24 | }); 25 | 26 | var dynamodb = new AWS.DynamoDB(); 27 | var datumVal = new Date() - 86400000; 28 | var params = { 29 | TableName: '', 30 | KeyConditionExpression: '#id = :iottopic and #ts >= :datum', 31 | ExpressionAttributeNames: { 32 | "#id": "id", 33 | "#ts": "timestamp" 34 | }, 35 | ExpressionAttributeValues: { 36 | ":iottopic": { "S" : "outTopic"}, 37 | ":datum": { "N" : datumVal.toString()} 38 | } 39 | };/* Create the context for applying the chart to the HTML canvas */ 40 | var tctx = $("#temperaturegraph").get(0).getContext("2d"); 41 | var hctx = $("#humiditygraph").get(0).getContext("2d");/* Set the options for our chart */ 42 | var options = { 43 | responsive: true, 44 | showLines: true, 45 | scales: { 46 | xAxes: [{ 47 | display: false 48 | }], 49 | yAxes: [{ 50 | ticks: { 51 | beginAtZero:true 52 | } 53 | }] 54 | } 55 | };/* Set the inital data */ 56 | var tinit = { 57 | labels: [], 58 | datasets: [ 59 | { 60 | label: "Temperature °C", 61 | backgroundColor: 'rgba(204,229,255,0.5)', 62 | borderColor: 'rgba(153,204,255,0.75)', 63 | data: [] 64 | } 65 | ] 66 | };var hinit = { 67 | labels: [], 68 | datasets: [ 69 | { 70 | label: "Humidity %", 71 | backgroundColor: 'rgba(229,204,255,0.5)', 72 | borderColor: 'rgba(204,153,255,0.75)', 73 | data: [] 74 | } 75 | ] 76 | };var temperaturegraph = new Chart.Line(tctx, {data: tinit, options: options}); 77 | var humiditygraph = new Chart.Line(hctx, {data: hinit, options: options});$(function() { 78 | getData(); 79 | $.ajaxSetup({ cache: false }); 80 | setInterval(getData, 300000); 81 | });/* Makes a scan of the DynamoDB table to set a data object for the chart */ 82 | function getData() { 83 | dynamodb.query(params, function(err, data) { 84 | if (err) { 85 | console.log(err); 86 | return null; 87 | } else {// placeholders for the data arrays 88 | var temperatureValues = []; 89 | var humidityValues = []; 90 | var labelValues = [];// placeholders for the data read 91 | var temperatureRead = 0.0; 92 | var humidityRead = 0.0; 93 | var timeRead = "";// placeholders for the high/low markers 94 | var temperatureHigh = -999.0; 95 | var humidityHigh = -999.0; 96 | var temperatureLow = 999.0; 97 | var humidityLow = 999.0; 98 | var temperatureHighTime = ""; 99 | var temperatureLowTime = ""; 100 | var humidityHighTime = ""; 101 | var humidityLowTime = "";for (var i in data['Items']) { 102 | // read the values from the dynamodb JSON packet 103 | temperatureRead = parseFloat(data['Items'][i]['payload']['M']['temperature']['N']); 104 | humidityRead = parseFloat(data['Items'][i]['payload']['M']['humidity']['N']); 105 | timeRead = new Date(data['Items'][i]['payload']['M']['datetime']['S']);// check the read values for high/low watermarks 106 | if (temperatureRead < temperatureLow) { 107 | temperatureLow = temperatureRead; 108 | temperatureLowTime = timeRead; 109 | } 110 | if (temperatureRead > temperatureHigh) { 111 | temperatureHigh = temperatureRead; 112 | temperatureHighTime = timeRead; 113 | } 114 | if (humidityRead < humidityLow) { 115 | humidityLow = humidityRead; 116 | humidityLowTime = timeRead; 117 | } 118 | if (humidityRead > humidityHigh) { 119 | humidityHigh = humidityRead; 120 | humidityHighTime = timeRead; 121 | }// append the read data to the data arrays 122 | temperatureValues.push(temperatureRead); 123 | humidityValues.push(humidityRead); 124 | labelValues.push(timeRead); 125 | }// set the chart object data and label arrays 126 | temperaturegraph.data.labels = labelValues; 127 | temperaturegraph.data.datasets[0].data = temperatureValues;humiditygraph.data.labels = labelValues; 128 | humiditygraph.data.datasets[0].data = humidityValues;// redraw the graph canvas 129 | temperaturegraph.update(); 130 | humiditygraph.update();// update the high/low watermark sections 131 | $('#t-high').text(Number(temperatureHigh).toFixed(2).toString() + '°C at ' + temperatureHighTime); 132 | $('#t-low').text(Number(temperatureLow).toFixed(2).toString() + '°C at ' + temperatureLowTime); 133 | $('#h-high').text(Number(humidityHigh).toFixed(2).toString() + '% at ' + humidityHighTime); 134 | $('#h-low').text(Number(humidityLow).toFixed(2).toString() + '% at ' + humidityLowTime);} 135 | }); 136 | } 137 | -------------------------------------------------------------------------------- /IoT_Sample_Data_Publishers/Bash_IoT_AWCLI2.sh: -------------------------------------------------------------------------------- 1 | # Adjecsted for AWS CLI Version 2, Stephen Borsay 2 | # code found at: https://aws.amazon.com/blogs/iot/integrating-iot-data-with-your-data-lake-with-new-aws-iot-analytics-features/ 3 | # changed 1000 iterations to 5 4 | 5 | 6 | 7 | #!/bin/bash 8 | 9 | mqtttopic='iota/topic/myhome_raspberrypi' 10 | iterations=5 11 | wait=5 12 | region='us-east-1' 13 | profile='default' 14 | 15 | for (( i = 1; i <= $iterations; i++)) { 16 | 17 | CURRENT_TS=`date +%s` 18 | DEVICE="P0"$((1 + $RANDOM % 5)) 19 | FLOW=$(( 60 + $RANDOM % 40 )) 20 | TEMP=$(( 15 + $RANDOM % 20 )) 21 | HUMIDITY=$(( 50 + $RANDOM % 40 )) 22 | VIBRATION=$(( 100 + $RANDOM % 40 )) 23 | 24 | # 3% chance of throwing an anomalous temperature reading 25 | if [ $(($RANDOM % 100)) -gt 97 ] 26 | then 27 | echo "Temperature out of range" 28 | TEMP=$(($TEMP*6)) 29 | fi 30 | 31 | echo "Publishing message $i/$ITERATIONS to IoT topic $mqtttopic:" 32 | echo "current_ts: $CURRENT_TS" 33 | echo "deviceid: $DEVICE" 34 | echo "flow: $FLOW" 35 | echo "temp: $TEMP" 36 | echo "humidity: $HUMIDITY" 37 | echo "vibration: $VIBRATION" 38 | 39 | aws2 iot-data publish --topic "$mqtttopic" --cli-binary-format raw-in-base64-out --payload "{\"deviceid\":\"$DEVICE\",\"current_ts\":$CURRENT_TS,\"flow\":$FLOW,\"temp\":$TEMP,\"humidity\":$HUMIDITY,\"vibration\":$VIBRATION}" --profile "$profile" --region "$region" 40 | 41 | sleep $wait 42 | } 43 | -------------------------------------------------------------------------------- /IoT_Sample_Data_Publishers/Bash_IoT_Local_Publisher.sh: -------------------------------------------------------------------------------- 1 | # code found at: https://aws.amazon.com/blogs/iot/integrating-iot-data-with-your-data-lake-with-new-aws-iot-analytics-features/ 2 | # changed 1000 iterations to 10 3 | 4 | 5 | #!/bin/bash 6 | 7 | mqtttopic='iota/topic/myhome_raspberrypi' 8 | iterations=10 9 | wait=5 10 | region='us-east-1' 11 | profile='default' 12 | 13 | for (( i = 1; i <= $iterations; i++)) { 14 | 15 | CURRENT_TS=`date +%s` 16 | DEVICE="P0"$((1 + $RANDOM % 5)) 17 | FLOW=$(( 60 + $RANDOM % 40 )) 18 | TEMP=$(( 15 + $RANDOM % 20 )) 19 | HUMIDITY=$(( 50 + $RANDOM % 40 )) 20 | VIBRATION=$(( 100 + $RANDOM % 40 )) 21 | 22 | # 3% chance of throwing an anomalous temperature reading 23 | if [ $(($RANDOM % 100)) -gt 97 ] 24 | then 25 | echo "Temperature out of range" 26 | TEMP=$(($TEMP*6)) 27 | fi 28 | 29 | echo "Publishing message $i/$ITERATIONS to IoT topic $mqtttopic:" 30 | echo "current_ts: $CURRENT_TS" 31 | echo "deviceid: $DEVICE" 32 | echo "flow: $FLOW" 33 | echo "temp: $TEMP" 34 | echo "humidity: $HUMIDITY" 35 | echo "vibration: $VIBRATION" 36 | 37 | aws iot-data publish --topic "$mqtttopic" --payload "{\"deviceid\":\"$DEVICE\",\"current_ts\":$CURRENT_TS,\"flow\":$FLOW,\"temp\":$TEMP,\"humidity\":$HUMIDITY,\"vibration\":$VIBRATION}" --profile "$profile" --region "$region" 38 | 39 | sleep $wait 40 | } 41 | -------------------------------------------------------------------------------- /IoT_Sample_Data_Publishers/Local_Publisher/README.md: -------------------------------------------------------------------------------- 1 | # clone project 2 | git clone \ 3 | --branch master --single-branch --depth 1 --no-tags \ 4 | https://github.com/garystafford/aws-iot-analytics-demo.git 5 | 6 | 7 | # publish sample messages to test cfn stack (5 messages) 8 | cd sample_data | topic defailt is: 'iot-device-data' 9 | 10 | python3 ./send_sample_messages.py -f raw_data_small.json -t iot-device-data 11 | 12 | -------------------------------------------------------------------------------- /IoT_Sample_Data_Publishers/Local_Publisher/raw_data_small.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "data": { 4 | "co": 0.004565749630211374, 5 | "humidity": 58.20000076293945, 6 | "light": true, 7 | "lpg": 0.007210160263049861, 8 | "motion": false, 9 | "smoke": 0.019158003725736547, 10 | "temp": 27 11 | }, 12 | "device_id": "5e:44:3b:f3:79:c8", 13 | "ts": 1594598726.5393324, 14 | "device": "iot-device-02" 15 | }, 16 | { 17 | "data": { 18 | "co": 0.005640155186117315, 19 | "humidity": 51.7, 20 | "light": false, 21 | "lpg": 0.008401139747010787, 22 | "motion": false, 23 | "smoke": 0.0225564297132387, 24 | "temp": 21.8 25 | }, 26 | "device_id": "f3:6b:f4:34:c0:17", 27 | "ts": 1594598727.0699694, 28 | "device": "iot-device-03" 29 | }, 30 | { 31 | "data": { 32 | "co": 0.00562960786515339, 33 | "humidity": 51.8, 34 | "light": false, 35 | "lpg": 0.008389771780906241, 36 | "motion": false, 37 | "smoke": 0.022523828027317963, 38 | "temp": 21.8 39 | }, 40 | "device_id": "f3:6b:f4:34:c0:17", 41 | "ts": 1594598730.7578712, 42 | "device": "iot-device-03" 43 | }, 44 | { 45 | "data": { 46 | "co": 0.004517441200106276, 47 | "humidity": 58.20000076293945, 48 | "light": true, 49 | "lpg": 0.007154892140546869, 50 | "motion": false, 51 | "smoke": 0.01900118011334872, 52 | "temp": 27 53 | }, 54 | "device_id": "5e:44:3b:f3:79:c8", 55 | "ts": 1594598731.4282842, 56 | "device": "iot-device-02" 57 | }, 58 | { 59 | "data": { 60 | "co": 0.005579086079598496, 61 | "humidity": 51.9, 62 | "light": false, 63 | "lpg": 0.00833523713478488, 64 | "motion": false, 65 | "smoke": 0.0223674724804285, 66 | "temp": 21.8 67 | }, 68 | "device_id": "f3:6b:f4:34:c0:17", 69 | "ts": 1594598734.4455285, 70 | "device": "iot-device-03" 71 | } 72 | ] 73 | -------------------------------------------------------------------------------- /IoT_Sample_Data_Publishers/Local_Publisher/send_sample_messages.py: -------------------------------------------------------------------------------- 1 | # Original can be found here https://github.com/garystafford/aws-iot-analytics-demo/blob/master/sample_data/send_sample_messages.py 2 | # Author Gary Stafford at AWS 3 | # Replace smaple JSON in this folder with your own JSON 4 | # Remeber Boto3 knows your AWS credentials from the AWS CLI So use ot in your home region 5 | # You can download Boto3 via --> **pip install boto3** 6 | 7 | import argparse 8 | import json 9 | import boto3 10 | 11 | 12 | def main(): 13 | # Parse command line arguments 14 | parser, args = parse_args() 15 | 16 | client = boto3.client('iot-data') 17 | count = 0 18 | 19 | with open(args.datafile) as f: 20 | messages = json.load(f) 21 | 22 | for message in messages: 23 | response = client.publish( 24 | topic=args.topic, 25 | qos=0, 26 | payload=json.dumps(message)) 27 | 28 | count += 1 29 | print(response) 30 | print('Total messages sent: {}/{}'.format(count, len(messages))) 31 | 32 | 33 | #Remeber Boto3 knows your AWS credentials from the AWS CLI So use ot in your home region 34 | # Read in command-line parameters 35 | def parse_args(): 36 | parser = argparse.ArgumentParser(description="Send sample messages to AWS IoT topic") 37 | parser.add_argument('-f', '--datafile', 38 | required=True, 39 | default='raw_data_small.json', 40 | help="file containing messages") 41 | parser.add_argument('-t', '--topic', 42 | required=True, 43 | default='iot-device-data', #this topic published to your home AWS Region 44 | help="topic to send messages to") 45 | 46 | args = parser.parse_args() 47 | return parser, args 48 | 49 | 50 | if __name__ == '__main__': 51 | main() 52 | -------------------------------------------------------------------------------- /IoT_Sample_Data_Publishers/SImulate_Device_In_Lambda_on_AWS.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | # Script to generate simulated IoT device parameters data 5 | 6 | import json 7 | import random 8 | import datetime 9 | import boto3 10 | import time 11 | 12 | ## Init AWSIoTMQTTClient 13 | 14 | 15 | deviceNames = ['SBS01', 'SBS02', 'SBS03', 'SBS04', 'SBS05'] 16 | 17 | iot = boto3.client('iot-data'); #iot = boto3.client('iot-data'); #'a3vvvvvvvees.iot.us-east-2.amazonaws.com' 18 | # myAWSIoTMQTTClient.configureEndpoint(host, port) 19 | #iot.configureEndpoint('a32qvvvvvvyees-ats.iot.eu-west-1.amazonaws.com', 8883) 20 | 21 | 22 | # generate Flow values 23 | def getFlowValues(): 24 | data = {} 25 | data['deviceValue'] = random.randint(60, 100) 26 | data['deviceParameter'] = 'Flow' 27 | data['deviceId'] = random.choice(deviceNames) 28 | data['dateTime'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") 29 | return data 30 | 31 | # generate Temperature values 32 | def getTemperatureValues(): 33 | data = {} 34 | data['deviceValue'] = random.randint(15, 35) 35 | data['deviceParameter'] = 'Temperature' 36 | data['deviceId'] = random.choice(deviceNames) 37 | data['dateTime'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") 38 | return data 39 | 40 | # generate Humidity values 41 | def getHumidityValues(): 42 | data = {} 43 | data['deviceValue'] = random.randint(50, 90) 44 | data['deviceParameter'] = 'Humidity' 45 | data['deviceId'] = random.choice(deviceNames) 46 | data['dateTime'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") 47 | return data 48 | 49 | # generate Sound values 50 | def getSoundValues(): 51 | data = {} 52 | data['deviceValue'] = random.randint(100, 140) 53 | data['deviceParameter'] = 'Sound' 54 | data['deviceId'] = random.choice(deviceNames) 55 | data['dateTime'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") 56 | return data 57 | 58 | # Generate each parameter's data input in varying proportions 59 | while True: 60 | time.sleep(1) 61 | rnd = random.random() 62 | if (0 <= rnd < 0.20): 63 | data = json.dumps(getFlowValues()) 64 | print(data) 65 | response = iot.publish( 66 | topic='xxx', #var AWS = require('aws-sdk'); 67 | #var iotdata = new AWS.IotData({endpoint: 'a32-2.amas.com' }); #return iotdata.publish(params, 68 | payload=data 69 | ) 70 | elif (0.20<= rnd < 0.55): 71 | data = json.dumps(getTemperatureValues()) 72 | print(data) 73 | response = iot.publish( 74 | topic='xxx', 75 | payload=data 76 | ) 77 | elif (0.55<= rnd < 0.70): 78 | data = json.dumps(getHumidityValues()) 79 | print(data) 80 | response = iot.publish( 81 | topic='xxx', 82 | payload=data 83 | ) 84 | else: 85 | data = json.dumps(getSoundValues()) 86 | print(data) 87 | response = iot.publish( 88 | topic='xxx', 89 | payload=data 90 | ) 91 | -------------------------------------------------------------------------------- /IoT_Sample_Data_Publishers/Simulate_Device_requires_certs.py: -------------------------------------------------------------------------------- 1 | ### Leverages the AWS IoT SDK for Python 2 | 3 | # Import SDK packages 4 | from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient 5 | import settings # importing configuration file 6 | import device # import device class 7 | import time 8 | import random 9 | import string 10 | import json 11 | import sys 12 | 13 | # create devices 14 | dev_names = ['soilSensor1', 'soilSensor2', 'soilSensor3'] 15 | devs = [] # set up a list to hold your devices 16 | for i in dev_names: 17 | devs.append(device.Device(i)) 18 | 19 | 20 | # Create a random 8-character string for connection id 21 | CLIENT_ID = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(8)) 22 | 23 | # create AWS IoT MQTT client 24 | client = AWSIoTMQTTClient(CLIENT_ID) 25 | 26 | print("Inside python code") 27 | print(sys.argv[1]) 28 | IOT_ENDPOINT_ADDRESS = json.loads(sys.argv[1])["endpointAddress"] 29 | 30 | # configure client endpoint / port information & then set up certs 31 | 32 | client.configureEndpoint(IOT_ENDPOINT_ADDRESS, settings.HOST_PORT) 33 | client.configureCredentials(settings.ROOT_CERT, settings.PRIVATE_KEY, settings.DEVICE_CERT) 34 | print(IOT_ENDPOINT_ADDRESS) 35 | 36 | # configure client connection behavior 37 | client.configureOfflinePublishQueueing(-1) # Infinite offline Publish queueing 38 | client.configureDrainingFrequency(2) # Draining: 2 Hz 39 | client.configureConnectDisconnectTimeout(10) # 10 sec 40 | client.configureMQTTOperationTimeout(5) # 5 sec 41 | 42 | print("Connecting to endpoint " + IOT_ENDPOINT_ADDRESS) 43 | client.connect() 44 | 45 | # start loop to begin publishing to topic 46 | while True: 47 | for dev in devs: 48 | client.publish("device/" + dev.name + "/devicePayload", dev.get_payload(), settings.QOS_LEVEL) 49 | print("Published message on topic " + "device/" + dev.name + "/devicePayload" + " with payload: " + dev.get_payload()) 50 | dev.update() # update the device with new data 51 | time.sleep(30) # just wait a sec before publishing next message 52 | -------------------------------------------------------------------------------- /IoT_Visualizer_Form_Lambda/CORS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "AllowedHeaders": [ 4 | "Authorization" 5 | ], 6 | "AllowedMethods": [ 7 | "GET" 8 | ], 9 | "AllowedOrigins": [ 10 | "*" 11 | ], 12 | "ExposeHeaders": [], 13 | "MaxAgeSeconds": 6000 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /IoT_Visualizer_Form_Lambda/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Title 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /IoT_Visualizer_Form_Lambda/main.js: -------------------------------------------------------------------------------- 1 | 2 | $(function() { // all jquery should be in "$(function() { }) document ready function" 3 | var uptime = new Array(); 4 | var humidity = new Array(); 5 | var temperature = new Array(); 6 | 7 | // Start by extracting YOUR FOLDER/ url from YOUR s3 bucket 8 | $.ajax({ 9 | type : "GET", 10 | url : "https://.s3.amazonaws.com/", 11 | dataType : "xml", 12 | success : function(xmlData){ 13 | var url = ""; 14 | keys = xmlData.getElementsByTagName("Key"); 15 | 16 | loadChart(uptime, temperature, humidity) 17 | //--------------------------------------// 18 | 19 | for(i=0; i < keys.length; i++) { 20 | url = keys[i].childNodes[0].nodeValue; 21 | 22 | // Find your locate your nested folder string 23 | pos = url.search("") //mine was folder2 24 | if(pos > -1) { 25 | // Detect nested folder with json file 26 | if(url.replace("/", "") != "") //mine was folder 2 27 | parseJson(url) 28 | } 29 | } 30 | // loadChart(uptime, temperature, humidity) 31 | }, 32 | error : function(){ 33 | alert("Could not retrieve XML file."); 34 | } 35 | }); 36 | 37 | // Parse JSON files 38 | var parseJson = function(url) { 39 | $.ajax({ 40 | type : "GET", 41 | url : "https://.s3.amazonaws.com/" + url, 42 | dataType : "json", 43 | async:false, 44 | success : function(jsonFile) { 45 | uptime.push(jsonFile.uptime); 46 | temperature.push(jsonFile.temperature) 47 | humidity.push(jsonFile.humidity) 48 | 49 | // $ajax by default asychrounous so, myChart.update() should update after success and response 50 | myChart.update(); 51 | //---------------------------------------// 52 | }, 53 | error : function(xhr, status, error) { 54 | console.error("JSON error: " + status); 55 | } 56 | }) 57 | } 58 | }) 59 | -------------------------------------------------------------------------------- /IoT_Visualizer_Form_Lambda/publicBucketPolicy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "Publsdg411145d", 6 | "Effect": "Allow", 7 | "Principal": "*", 8 | "Action": [ 9 | "s3:GetObject", 10 | "s3:GetObjectVersion" 11 | ], 12 | "Resource": "arn:aws:s3:::/*" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /IoT_Visualizer_Form_Lambda/visualizer.js: -------------------------------------------------------------------------------- 1 | var myChart; // it should be global, otherwise it will be create "javascript execution context" issue 2 | var loadChart = function(uptime, temperature, humidity) { 3 | var ctx = $('#myChart'); 4 | 5 | myChart = new Chart(ctx, { 6 | type: 'line', 7 | data: { 8 | labels: uptime, 9 | datasets: [ 10 | { 11 | label: "Temperature", 12 | data: temperature, 13 | fill: false, 14 | borderColor: "rgb(255, 0, 0)", 15 | lineTension: 0.1 16 | }, 17 | { 18 | label: "Humidity", 19 | data: humidity, 20 | fill: false, 21 | borderColor: "rgb(0, 0, 255)", 22 | lineTension: 0.1 23 | } 24 | ] 25 | }, 26 | options: {} 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /KinesisFirehose_Visualizer/CORS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "AllowedHeaders": [ 4 | "Authorization" 5 | ], 6 | "AllowedMethods": [ 7 | "GET" 8 | ], 9 | "AllowedOrigins": [ 10 | "*" 11 | ], 12 | "ExposeHeaders": [], 13 | "MaxAgeSeconds": 6000 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /KinesisFirehose_Visualizer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Title 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 |
19 | 20 |
21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /KinesisFirehose_Visualizer/main.js: -------------------------------------------------------------------------------- 1 | var uptime = []; 2 | var humidity = []; 3 | var temperature = []; 4 | 5 | // Parse file as text 6 | var parseText = function(url) { 7 | var values ={ "uptime":"", "temperature":"", "humidity":"" }; 8 | $.ajax({ 9 | type : "GET", 10 | url : "https://.s3.amazonaws.com/" + url, //you will ned to addyour region to url too -> 11 | async : false, //if your base bucket region != your home region 12 | dataType : "text", 13 | success : function(txtFile){ 14 | var jsonArray; 15 | // Convert text file to JSON Array 16 | jsonArray = parseToJSONArray(txtFile) 17 | // Get Values from JSONArray 18 | jsonArray.forEach(getValuesFromJSON) 19 | 20 | values.uptime = uptime 21 | values.temperature = temperature 22 | values.humidity = humidity 23 | }, 24 | error : function(xhr, status, error){ 25 | alert(status + ' ' + error); 26 | } 27 | }); 28 | } 29 | 30 | 31 | // Get uptime, temperature and humidity from json 32 | var getValuesFromJSON = function(json, index, JSONArray) { 33 | json = JSON.parse(json) 34 | uptime.push(json.uptime); 35 | temperature.push(json.temperature) 36 | humidity.push(json.humidity) 37 | } 38 | 39 | // This function converts the text file from server to a JSON Array 40 | var parseToJSONArray = function(txtFile) { 41 | var json = []; 42 | var temp = ""; 43 | var i = 0 44 | while(i < txtFile.length) { 45 | // console.log(txtFile[i]) 46 | if(txtFile[i] != " ") { 47 | temp += txtFile[i] 48 | if(txtFile[i] == "}") { 49 | i = i+1 50 | json.push(temp) 51 | temp = "" 52 | } 53 | } 54 | i+=1 55 | } 56 | return json; 57 | } 58 | 59 | // Start by extracting key/ url from s3 bucket 60 | $.ajax({ 61 | type : "GET", 62 | url : "https://.s3.amazonaws.com/", //you will ned to addyour region to url too 63 | async : false, //if your base bucket region != your home region 64 | dataType : "xml", 65 | success : function(xmlData, values){ 66 | var url = ""; 67 | var values = {}; 68 | keys = xmlData.getElementsByTagName("Key"); 69 | for(i=0; i < keys.length; i++) { 70 | url = keys[i].childNodes[0].nodeValue; 71 | parseText(url) 72 | } 73 | 74 | 75 | // console.log('Uptime') 76 | // console.log(uptime) 77 | // console.log('Humidity') 78 | // console.log(humidity) 79 | // console.log('Temperature') 80 | // console.log(temperature) 81 | // Load values in Chart 82 | loadLineChart(uptime,temperature,humidity); 83 | loadBarChart(uptime,temperature,humidity); 84 | }, 85 | error : function(){ 86 | alert("Could not retrieve XML file."); 87 | } 88 | }) 89 | -------------------------------------------------------------------------------- /KinesisFirehose_Visualizer/visualizer.js: -------------------------------------------------------------------------------- 1 | var loadLineChart = function(uptime, temperature, humidity) { 2 | var lineChart = $('#lineChart'); 3 | 4 | var myChart1 = new Chart(lineChart, { 5 | type: 'line', 6 | data: { 7 | labels: uptime, 8 | datasets: [ 9 | { 10 | label: "Temperature", 11 | data: temperature, 12 | fill: false, 13 | borderColor: "rgb(255, 0, 0)", 14 | lineTension: 0.1 15 | }, 16 | { 17 | label: "Humidity", 18 | data: humidity, 19 | fill: false, 20 | borderColor: "rgb(0, 0, 255)", 21 | lineTension: 0.1 22 | } 23 | ] 24 | }, 25 | options: { 26 | responsive: true, 27 | title: { 28 | display: true, 29 | text: 'Uptime', 30 | position: 'bottom' 31 | } 32 | } 33 | }); 34 | } 35 | 36 | var loadBarChart = function(uptime, temperature, humidity) { 37 | var barChart = $('#barChart'); 38 | 39 | var myChart2 = new Chart(barChart, { 40 | type: 'bar', 41 | data: { 42 | labels: uptime, 43 | datasets: [ 44 | { 45 | label: "Temperature", 46 | data: temperature, 47 | backgroundColor: "rgb(255, 0, 0)" 48 | }, 49 | { 50 | label: "Humidity", 51 | data: humidity, 52 | backgroundColor: "rgb(0, 0, 255)" 53 | } 54 | ] 55 | }, 56 | options: { 57 | responsive: true, 58 | barValueSpacing: 20, 59 | title: { 60 | display: true, 61 | text: 'Uptime', 62 | position: 'bottom' 63 | } 64 | } 65 | }); 66 | } 67 | 68 | 69 | -------------------------------------------------------------------------------- /Lambda_Publisher/IoT-Publisher_NonAsync.js: -------------------------------------------------------------------------------- 1 | var AWS = require('aws-sdk'); 2 | 3 | var iotdata = new AWS.IotData({endpoint: '' }); 4 | 5 | exports.handler = (event) => { 6 | console.log("The event object is: " + JSON.stringify(event)); 7 | var params = { 8 | topic: "", //intopic_thing_7 9 | payload: JSON.stringify(event), //event.Temperature, event.Humidity, event.Time, event.Device_Id 10 | qos: 0 11 | }; 12 | 13 | return iotdata.publish(params, function(err, data) { 14 | if (err) { 15 | console.log("If error: " + JSON.stringify(err)); 16 | } 17 | else { 18 | console.log("Success"); 19 | } 20 | }) 21 | }; 22 | -------------------------------------------------------------------------------- /Lambda_Publisher/IoT_Pubisher.js: -------------------------------------------------------------------------------- 1 | //If this prublishes twice see other function in same directory 2 | 3 | var AWS = require('aws-sdk'); 4 | 5 | var iotdata = new AWS.IotData({endpoint: '' }); 6 | 7 | exports.handler = async (event) => { 8 | console.log("The event object is: " + JSON.stringify(event)); 9 | var params = { 10 | topic: "", //intopic_thing_7 11 | payload: JSON.stringify(event), //event.Temperature, event.Humidity, event.Time, event.Device_Id 12 | qos: 0 13 | }; 14 | 15 | return iotdata.publish(params, function(err, data) { 16 | if (err) { 17 | console.log("If error: " + JSON.stringify(err)); 18 | } 19 | else { 20 | console.log("Success"); 21 | } 22 | }).promise(); //https://aws.amazon.com/blogs/developer/support-for-promises-in-the-sdk/ 23 | }; 24 | -------------------------------------------------------------------------------- /Lambda_Publisher/IoT_Publisher.py: -------------------------------------------------------------------------------- 1 | #https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/iot-data.html#IoTDataPlane.Client.publish 2 | #https://iotespresso.com/publishing-from-lambda-to-an-aws-iot-topic/ 3 | 4 | import json 5 | import boto3 6 | 7 | client = boto3.client('iot-data', region_name='us-east-2') 8 | 9 | def lambda_handler(event, context): 10 | print(event) 11 | # TODO implement 12 | # Change topic, qos and payload 13 | response = client.publish( 14 | topic='iot/fromLambda', 15 | qos=1, 16 | payload=json.dumps({"foot":"ball"}) #from web input via APi Gateway: payload=json.dumps(event['queryStringParameters']) 17 | ) 18 | print(response) 19 | 20 | return { 21 | 'statusCode': 200, 22 | 'body': json.dumps('Published to topic') 23 | } 24 | -------------------------------------------------------------------------------- /Lambda_Publisher/websiteInputBox.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 |
6 | 7 | 8 | -------------------------------------- 9 | alternate 10 | --------------------------------------- 11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 |
21 |
22 | 23 | -------------------------------------- 24 | alternate 25 | --------------------------------------- 26 | 27 | 28 | 29 | 30 | jQuery Form Example 31 | 35 | 36 | 37 | 38 |
39 |

Processing an AJAX Form

40 | 41 |
42 |
43 | 44 | 51 |
52 | 55 |
56 |
57 | 58 | 59 | 60 | 61 | -------------------------------------- 62 | alternate for 2 key/value pairs 63 | --------------------------------------- 64 | 65 |
66 |
67 | 68 | 69 |
70 |
71 | 72 | 73 |
74 |
75 | 76 |
77 |
78 | 79 | { 80 | 'statusCode': 302, 81 | 'headers': { 82 | 'Location': 'https://redirect.example.com/path' 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Level3_design/CORS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "AllowedHeaders": [ 4 | "Authorization" 5 | ], 6 | "AllowedMethods": [ 7 | "GET" 8 | ], 9 | "AllowedOrigins": [ 10 | "*" 11 | ], 12 | "ExposeHeaders": [], 13 | "MaxAgeSeconds": 6000 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /Level3_design/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Document 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 |
20 | 21 |
22 |

Dashboard

23 |
24 | 25 | 26 |
27 |
28 | 29 | 30 | 31 |
32 |
33 |

34 | Line Chart 35 |

36 |
37 |
38 |
39 |
40 |
41 | 42 | 43 |
44 |
45 |

46 | Bar Chart 47 |

48 |
49 |
50 |
51 |
52 |
53 | 54 |
55 | 56 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /Level3_design/index.js: -------------------------------------------------------------------------------- 1 | var AWS = require('aws-sdk'); 2 | //configuring the AWS environment 3 | //default name for this Lambda fuction should be 'index.js' 4 | 5 | var s3 = new AWS.S3({ apiVersion: '2006-03-01' }); 6 | 7 | exports.handler = function (event, context, callback) { 8 | 9 | let responseData = []; 10 | let promiseArr = []; 11 | var params = { 12 | Bucket: "", 13 | MaxKeys: 50 14 | }; 15 | s3.listObjects(params, (err, objects) => { 16 | if (err) 17 | return console.log(err); 18 | if (objects && objects.Contents && objects.Contents.length > 0) { 19 | let contents = objects.Contents; 20 | // console.log(contents); 21 | for (let index = 0; index < contents.length; index++) { 22 | const element = contents[index]; 23 | const regex = /*/g; // YOUR KEY/FOLDER NAME FOLLOWED BY a '*' 24 | if (regex.test(element.Key)) { 25 | var params1 = { 26 | Bucket: "", 27 | Key: element.Key 28 | }; 29 | if (element.Key !== '/') { 30 | promiseArr.push(new Promise((resolve, reject) => { 31 | s3.getObject(params1, (err, data) => { 32 | if (err) { 33 | console.log(err); 34 | reject(); 35 | } else { 36 | try { 37 | let parsedData = JSON.parse(data.Body.toString('utf-8')); 38 | if(parsedData && parsedData.hasOwnProperty('humidity') && parsedData.hasOwnProperty('temperature') && parsedData.hasOwnProperty('uptime')){ 39 | responseData.push(parsedData); 40 | } 41 | resolve(); 42 | } catch (error) { 43 | console.log(error) 44 | resolve(); 45 | } 46 | } 47 | }) 48 | })) 49 | 50 | } 51 | } 52 | } 53 | 54 | Promise.all(promiseArr) 55 | .then(res => { 56 | // console.log(JSON.stringify(responseData)); 57 | callback(null, responseData); 58 | }) 59 | .catch(err => { 60 | console.log('Error ', err) 61 | callback(err); 62 | }); 63 | } 64 | }) 65 | } 66 | 67 | -------------------------------------------------------------------------------- /Level4_design/1_Synchronous_IoT/CORS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "AllowedHeaders": [ 4 | "Authorization" 5 | ], 6 | "AllowedMethods": [ 7 | "GET" 8 | ], 9 | "AllowedOrigins": [ 10 | "*" 11 | ], 12 | "ExposeHeaders": [], 13 | "MaxAgeSeconds": 3000 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /Level4_design/1_Synchronous_IoT/IoT_Payload_Producer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mqtttopic='' #Example: 'outTopic' 4 | iterations=10 5 | wait=5 6 | region='' #Example: 'us-east-1' 7 | profile='default' 8 | 9 | for (( i = 1; i <= $iterations; i++)) { 10 | 11 | #CURRENT_TS=`date +%s` 12 | #DEVICE="P0"$((1 + $RANDOM % 5)) 13 | #FLOW=$(( 60 + $RANDOM % 40 )) 14 | #TEMP=$(( 15 + $RANDOM % 20 )) 15 | #HUMIDITY=$(( 50 + $RANDOM % 40 )) 16 | #VIBRATION=$(( 100 + $RANDOM % 40 )) 17 | temperature=$(( 15 + $RANDOM % 20 )) 18 | humidity=$(( 50 + $RANDOM % 40 )) 19 | 20 | # 3% chance of throwing an anomalous temperature reading 21 | if [ $(($RANDOM % 100)) -gt 97 ] 22 | then 23 | echo "Temperature out of range" 24 | TEMP=$(($TEMP*6)) 25 | fi 26 | 27 | echo "Publishing message $i/$ITERATIONS to IoT topic $mqtttopic:" 28 | #echo "current_ts: $CURRENT_TS" 29 | #echo "deviceid: $DEVICE" 30 | #echo "flow: $FLOW" 31 | echo "temperature: $temperature" 32 | echo "humidity: $humidity" 33 | #echo "vibration: $VIBRATION" 34 | 35 | #use below for AWS CLI V1 36 | #aws iot-data publish --topic "$mqtttopic" --payload "{\"temperature\":$temperature,\"humidity\":$humidity}" --profile "$profile" --region "$region" 37 | 38 | #use below for AWS CLI V2 39 | aws iot-data publish --topic "$mqtttopic" --cli-binary-format raw-in-base64-out --payload "{\"temperature\":$temperature,\"humidity\":$humidity}" --profile "$profile" --region "$region" 40 | 41 | sleep $wait 42 | } 43 | -------------------------------------------------------------------------------- /Level4_design/1_Synchronous_IoT/Open_Bucket_Policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "PublicRea2411145d", 6 | "Effect": "Allow", 7 | "Principal": "*", 8 | "Action": [ 9 | "s3:GetObject", 10 | "s3:GetObjectVersion" 11 | ], 12 | "Resource": "arn:aws:s3:::/*" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /Level4_design/1_Synchronous_IoT/README.md: -------------------------------------------------------------------------------- 1 | ![synamicdataweb](https://user-images.githubusercontent.com/16296900/149360898-f6aa0b84-c406-4497-b804-91943707f48f.JPG) 2 | -------------------------------------------------------------------------------- /Level4_design/1_Synchronous_IoT/Timestamp_to_time.js: -------------------------------------------------------------------------------- 1 | let unix_timestamp = 1549312452 2 | // Create a new JavaScript Date object based on the timestamp 3 | // multiplied by 1000 so that the argument is in milliseconds, not seconds. 4 | var date = new Date(unix_timestamp); // multiply by a thousand if seconds not milliseconds 5 | // Hours part from the timestamp 6 | var hours = date.getHours(); 7 | // Minutes part from the timestamp 8 | var minutes = "0" + date.getMinutes(); 9 | // Seconds part from the timestamp 10 | var seconds = "0" + date.getSeconds(); 11 | 12 | // Will display time in 10:30:23 format 13 | var formattedTime = hours + ':' + minutes.substr(-2) + ':' + seconds.substr(-2); 14 | 15 | console.log(formattedTime); 16 | -------------------------------------------------------------------------------- /Level4_design/1_Synchronous_IoT/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Dashboard 9 | 10 | 11 | 12 |
13 |

Synchronous Weather Data on Interval

14 | 15 |
16 |
17 |

Line Chart

18 |
19 |
20 |
21 |
22 |
23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Level4_design/1_Synchronous_IoT/main.js: -------------------------------------------------------------------------------- 1 | let humArr = [], tempArr = [], upArr = []; 2 | let myChart = Highcharts.chart('container1', { 3 | 4 | title: { 5 | text: 'Line chart' 6 | }, 7 | 8 | subtitle: { 9 | text: 'subtitle' 10 | }, 11 | 12 | yAxis: { 13 | title: { 14 | text: 'Value' 15 | } 16 | }, 17 | 18 | xAxis: { 19 | categories: upArr 20 | }, 21 | 22 | legend: { 23 | layout: 'vertical', 24 | align: 'right', 25 | verticalAlign: 'middle' 26 | }, 27 | 28 | plotOptions: { 29 | series: { 30 | label: { 31 | connectorAllowed: false 32 | } 33 | } 34 | }, 35 | series: [{ 36 | name: 'Humdity', 37 | data: [] 38 | }, { 39 | name: 'Temperature', 40 | data: [] 41 | }], 42 | 43 | responsive: { 44 | rules: [{ 45 | condition: { 46 | maxWidth: 500 47 | }, 48 | chartOptions: { 49 | legend: { 50 | layout: 'horizontal', 51 | align: 'center', 52 | verticalAlign: 'bottom' 53 | } 54 | } 55 | }] 56 | } 57 | }); 58 | 59 | let getWheatherData = function () { 60 | $.ajax({ 61 | type: "GET", 62 | url: "", //example: https://mydatabucket.s3.amazonaws.com/myKey" 63 | dataType: "json", 64 | async: false, 65 | success: function (data) { 66 | console.log('data', data); 67 | drawChart(data); 68 | }, 69 | error: function (xhr, status, error) { 70 | console.error("JSON error: " + status); 71 | } 72 | }); 73 | } 74 | 75 | let drawChart = function (data) { 76 | 77 | let { humidity, temperature, timestamps } = data; 78 | 79 | humArr.push(Number(humidity)); 80 | tempArr.push(Number(temperature)); 81 | upArr.push(Number(timestamps)); 82 | 83 | myChart.series[0].setData(humArr , true) 84 | myChart.series[1].setData(tempArr , true) 85 | } 86 | 87 | let intervalTime = 3 * 1000; // 3 second interval polling, change as you like 88 | setInterval(() => { 89 | getWheatherData(); 90 | }, intervalTime); 91 | -------------------------------------------------------------------------------- /Level4_design/1_Synchronous_IoT/timestamp_RulesQueryStatement: -------------------------------------------------------------------------------- 1 | SELECT *, timestamp() AS timestamp FROM '' 2 | -------------------------------------------------------------------------------- /Level4_design/2_ Asynchronous_IoT_Beginner/Basic_website/README.md: -------------------------------------------------------------------------------- 1 | index.html and main.js are in base level directory 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Level4_design/2_ Asynchronous_IoT_Beginner/Better_website/README.md: -------------------------------------------------------------------------------- 1 | 2 | ![websAdv](https://user-images.githubusercontent.com/16296900/149360729-2f264eed-e50f-4490-9c92-c9c0b435d8d9.JPG) 3 | -------------------------------------------------------------------------------- /Level4_design/2_ Asynchronous_IoT_Beginner/Better_website/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Dashboard 9 | 10 | 11 | 12 |
13 |

Asynchronous IoT Weather Data with AWS WebSockets

14 | 15 |
16 |
17 |

Line Chart

18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | 26 | 44 | 45 | 46 | 47 |
48 | 49 |
50 |
51 | 52 |
53 |

54 | Temperature Gauge with Degrees in Fehr/Cel 55 |

56 |
57 |
58 | 59 | 60 | 61 |
62 |
63 |
64 |

65 | Humidity Guage showing %of water saturation 66 |

67 |
68 |
69 | 70 | 71 |
72 |
73 |
74 |

75 | Epoch/UNIX time, expect many ticks per Second 76 |

77 |
78 |
79 | 80 |
81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Level4_design/2_ Asynchronous_IoT_Beginner/CORS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "AllowedHeaders": [ 4 | "Authorization" 5 | ], 6 | "AllowedMethods": [ 7 | "GET" 8 | ], 9 | "AllowedOrigins": [ 10 | "*" 11 | ], 12 | "ExposeHeaders": [], 13 | "MaxAgeSeconds": 6000 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /Level4_design/2_ Asynchronous_IoT_Beginner/IoT_Bash_Producer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mqtttopic='' #Example: 'iot/sregsfg' 4 | iterations=10 5 | wait=5 6 | region='' #Example: 'us-east-1' 7 | profile='default' 8 | 9 | for (( i = 1; i <= $iterations; i++)) { 10 | 11 | #CURRENT_TS=`date +%s` 12 | #DEVICE="P0"$((1 + $RANDOM % 5)) 13 | #FLOW=$(( 60 + $RANDOM % 40 )) 14 | #TEMP=$(( 15 + $RANDOM % 20 )) 15 | #HUMIDITY=$(( 50 + $RANDOM % 40 )) 16 | #VIBRATION=$(( 100 + $RANDOM % 40 )) 17 | temperature=$(( 15 + $RANDOM % 20 )) 18 | humidity=$(( 50 + $RANDOM % 40 )) 19 | 20 | # 3% chance of throwing an anomalous temperature reading 21 | if [ $(($RANDOM % 100)) -gt 97 ] 22 | then 23 | echo "Temperature out of range" 24 | TEMP=$(($TEMP*6)) 25 | fi 26 | 27 | echo "Publishing message $i/$ITERATIONS to IoT topic $mqtttopic:" 28 | #echo "current_ts: $CURRENT_TS" 29 | #echo "deviceid: $DEVICE" 30 | #echo "flow: $FLOW" 31 | echo "temperature: $temperature" 32 | echo "humidity: $humidity" 33 | #echo "vibration: $VIBRATION" 34 | 35 | #use below for AWS CLI V1 36 | #aws iot-data publish --topic "$mqtttopic" --payload "{\"temperature\":$temperature,\"humidity\":$humidity}" --profile "$profile" --region "$region" 37 | 38 | #use below for AWS CLI V2 39 | aws iot-data publish --topic "$mqtttopic" --cli-binary-format raw-in-base64-out --payload "{\"temperature\":$temperature,\"humidity\":$humidity}" --profile "$profile" --region "$region" 40 | 41 | sleep $wait 42 | } 43 | -------------------------------------------------------------------------------- /Level4_design/2_ Asynchronous_IoT_Beginner/IoT_Core_Rules_Query_Statement.sql: -------------------------------------------------------------------------------- 1 | SELECT *,timestamp() AS timestamps FROM 'iot/#' 2 | -------------------------------------------------------------------------------- /Level4_design/2_ Asynchronous_IoT_Beginner/IoT_Test_Payload.json: -------------------------------------------------------------------------------- 1 | Test For Lambda 2 | 3 | 4 | 5 | { 6 | "temperature": 55, 7 | "humidity": 66, 8 | "timestamps": 12345 9 | } 10 | 11 | 12 | Test for IoT Core (Our RQS adds Timestamps for us) 13 | 14 | { 15 | "temperature": 77, 16 | "humidity": 88 17 | } 18 | 19 | -------------------------------------------------------------------------------- /Level4_design/2_ Asynchronous_IoT_Beginner/Open_Bucket_Policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "PublicR34561145d", 6 | "Effect": "Allow", 7 | "Principal": "*", 8 | "Action": [ 9 | "s3:GetObject", 10 | "s3:GetObjectVersion" 11 | ], 12 | "Resource": "arn:aws:s3:::/*" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /Level4_design/2_ Asynchronous_IoT_Beginner/README.md: -------------------------------------------------------------------------------- 1 | part 2 2 | -------------------------------------------------------------------------------- /Level4_design/2_ Asynchronous_IoT_Beginner/Test_Script_for_Browser.js: -------------------------------------------------------------------------------- 1 | const socket = new WebSocket('wss://') // Example: 'wss://3143544j.execute-api.us-east-1.amazonaws.com/production' 2 | 3 | socket.addEventListener('open', event => { 4 | console.log('WebSocket is connected') 5 | }) 6 | 7 | socket.addEventListener('message', event => { 8 | 9 | console.log('Incoming IoT Payload:', event.data) // for JSON test event 10 | }) 11 | -------------------------------------------------------------------------------- /Level4_design/2_ Asynchronous_IoT_Beginner/Test_index_for_browser.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Level4_design/2_ Asynchronous_IoT_Beginner/connection_Lambda.js: -------------------------------------------------------------------------------- 1 | 2 | const AWS = require('aws-sdk') 3 | 4 | exports.handler = async (event, context) => { 5 | 6 | console.log(event); 7 | let connectionId = event.requestContext.connectionId; 8 | console.log("myConnectionID is: ", connectionId) //Go To AWS CloudWatch Service for your Connection ID 9 | 10 | const response = { 11 | statusCode: 200, 12 | body: JSON.stringify('Hello from Lambda!'), 13 | }; 14 | return response; //need a response or we get disconnected immediatly 15 | 16 | }; 17 | -------------------------------------------------------------------------------- /Level4_design/2_ Asynchronous_IoT_Beginner/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Dashboard 9 | 10 | 11 | 12 |
13 |

Asynchronous Weather Data with AWS Websockets

14 | 15 |
16 |
17 |

Line Chart

18 |
19 |
20 |
21 |
22 |
23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Level4_design/2_ Asynchronous_IoT_Beginner/main.js: -------------------------------------------------------------------------------- 1 | let humArr = [], tempArr = [], upArr = []; 2 | let myChart = Highcharts.chart('container1', { 3 | 4 | title: { 5 | text: 'Line chart' 6 | }, 7 | 8 | subtitle: { 9 | text: 'subtitle' 10 | }, 11 | 12 | yAxis: { 13 | title: { 14 | text: 'Value' 15 | } 16 | }, 17 | 18 | xAxis: { 19 | categories: upArr 20 | }, 21 | 22 | legend: { 23 | layout: 'vertical', 24 | align: 'right', 25 | verticalAlign: 'middle' 26 | }, 27 | 28 | plotOptions: { 29 | series: { 30 | label: { 31 | connectorAllowed: false 32 | } 33 | } 34 | }, 35 | series: [{ 36 | name: 'Humdity', 37 | data: [] 38 | }, { 39 | name: 'Temperature', 40 | data: [] 41 | }], 42 | 43 | responsive: { 44 | rules: [{ 45 | condition: { 46 | maxWidth: 500 47 | }, 48 | chartOptions: { 49 | legend: { 50 | layout: 'horizontal', 51 | align: 'center', 52 | verticalAlign: 'bottom' 53 | } 54 | } 55 | }] 56 | } 57 | 58 | }); 59 | 60 | 61 | const socket = new WebSocket('wss://') //example: 'wss://3143544j.execute-api.us-east-1.amazonaws.com/production' 62 | 63 | socket.addEventListener('open', event => { 64 | console.log('WebSocket is connected, now check for your new Connection ID in Cloudwatch on AWS') 65 | }) 66 | 67 | socket.addEventListener('message', event => { 68 | 69 | console.log('Your iot payload is:', event.data); 70 | drawChart(event.data); 71 | }) 72 | 73 | 74 | 75 | let drawChart = function (data) { 76 | 77 | 78 | var IoT_Payload = JSON.parse(data); 79 | console.log("our json object", IoT_Payload); 80 | console.log(IoT_Payload.temperature); 81 | 82 | 83 | let { humidity, temperature, timestamps } = IoT_Payload; 84 | 85 | 86 | humArr.push(Number(IoT_Payload.humidity)); 87 | tempArr.push(Number(IoT_Payload.temperature)); 88 | upArr.push(Number(IoT_Payload.timestamps)); 89 | 90 | 91 | myChart.series[0].setData(humArr , true) 92 | myChart.series[1].setData(tempArr , true) 93 | } 94 | -------------------------------------------------------------------------------- /Level4_design/2_ Asynchronous_IoT_Beginner/send_IoT_Message_Lambd.py: -------------------------------------------------------------------------------- 1 | #Don't forget to add 'ExecuteAPI' to your permissions as inline policy for this lambda function 2 | 3 | import json 4 | import boto3 5 | 6 | Websocket_HTTPS_URL = "" 7 | client = boto3.client("apigatewaymanagementapi", endpoint_url = Websocket_HTTPS_URL) 8 | 9 | Test_Message = json.dumps({ "message": "Hello from lambda, hardcoded test message"}) 10 | 11 | def lambda_handler(event, context): 12 | print(event) 13 | connectionId = "" #must manually enter for this beginner version 14 | IoT_Message = json.dumps(event) 15 | #AWS API Gateway API's require 'key=value' arguments 16 | #https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/apigatewaymanagementapi.html#ApiGatewayManagementApi.Client.post_to_connection 17 | response = client.post_to_connection(ConnectionId = connectionId, Data = IoT_Message) 18 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Basic_website/README.md: -------------------------------------------------------------------------------- 1 | ![synamicdataweb](https://user-images.githubusercontent.com/16296900/149360972-b7e63682-3851-4d18-93f3-b6f60354e1c8.JPG) 2 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Basic_website/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Dashboard 9 | 10 | 11 | 12 |
13 |

Asynchronous Weather Data with AWS Websockets

14 | 15 |
16 |
17 |

Line Chart

18 |
19 |
20 |
21 |
22 |
23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Basic_website/main.js: -------------------------------------------------------------------------------- 1 | let humArr = [], tempArr = [], upArr = []; 2 | let myChart = Highcharts.chart('container1', { 3 | 4 | title: { 5 | text: 'Line chart' 6 | }, 7 | 8 | subtitle: { 9 | text: 'subtitle' 10 | }, 11 | 12 | yAxis: { 13 | title: { 14 | text: 'Value' 15 | } 16 | }, 17 | 18 | xAxis: { 19 | categories: upArr 20 | }, 21 | 22 | legend: { 23 | layout: 'vertical', 24 | align: 'right', 25 | verticalAlign: 'middle' 26 | }, 27 | 28 | plotOptions: { 29 | series: { 30 | label: { 31 | connectorAllowed: false 32 | } 33 | } 34 | }, 35 | series: [{ 36 | name: 'Humdity', 37 | data: [] 38 | }, { 39 | name: 'Temperature', 40 | data: [] 41 | }], 42 | 43 | responsive: { 44 | rules: [{ 45 | condition: { 46 | maxWidth: 500 47 | }, 48 | chartOptions: { 49 | legend: { 50 | layout: 'horizontal', 51 | align: 'center', 52 | verticalAlign: 'bottom' 53 | } 54 | } 55 | }] 56 | } 57 | 58 | }); 59 | 60 | 61 | const socket = new WebSocket('') 62 | 63 | socket.addEventListener('open', event => { 64 | console.log('WebSocket is connected, now check for your new Connection ID in Cloudwatch on AWS') 65 | }) 66 | 67 | 68 | socket.addEventListener('message', event => { 69 | 70 | console.log('Your iot payload is:', event.data); 71 | drawChart(event.data); 72 | }) 73 | 74 | 75 | 76 | let drawChart = function (data) { 77 | 78 | 79 | var IoT_Payload = JSON.parse(data); 80 | console.log("our json object", IoT_Payload); 81 | 82 | let { humidity, temperature, timestamps } = IoT_Payload; 83 | 84 | humArr.push(Number(IoT_Payload.humidity)); 85 | tempArr.push(Number(IoT_Payload.temperature)); 86 | upArr.push(Number(IoT_Payload.timestamps)); 87 | 88 | myChart.series[0].setData(humArr , true) 89 | myChart.series[1].setData(tempArr , true) 90 | } 91 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Better_website/README.md: -------------------------------------------------------------------------------- 1 | ![websAdv](https://user-images.githubusercontent.com/16296900/149361071-b67dab05-ae15-4ef0-96b1-af0b2b6a1c5f.JPG) 2 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Better_website/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Dashboard 9 | 10 | 11 | 12 |
13 |

Asynchronous IoT Weather Data with AWS WebSockets

14 | 15 |
16 |
17 |

Line Chart

18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | 26 | 44 | 45 | 46 | 47 |
48 | 49 |
50 |
51 | 52 |
53 |

54 | Temperature Gauge with Degrees in Fehr/Cel 55 |

56 |
57 |
58 | 59 | 60 | 61 |
62 |
63 |
64 |

65 | Humidity Guage showing %of water saturation 66 |

67 |
68 |
69 | 70 | 71 |
72 |
73 |
74 |

75 | Epoch/UNIX time, expect many ticks per Second 76 |

77 |
78 |
79 | 80 |
81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/CORS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "AllowedHeaders": [ 4 | "Authorization" 5 | ], 6 | "AllowedMethods": [ 7 | "GET" 8 | ], 9 | "AllowedOrigins": [ 10 | "*" 11 | ], 12 | "ExposeHeaders": [], 13 | "MaxAgeSeconds": 6000 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Chartjs_Streaming/README.md: -------------------------------------------------------------------------------- 1 | ![image](https://user-images.githubusercontent.com/16296900/149674011-6ed5f91a-3f16-44c3-9903-4b91d2dedc82.png) 2 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Chartjs_Streaming/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 18 | 19 |
20 |
21 | 22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | 30 | 48 | 49 | 50 | 51 |
52 | 53 |
54 |
55 | 56 |
57 |

58 | Temperature Gauge with Degrees in Fehr/Cel 59 |

60 |
61 |
62 | 63 | 64 | 65 |
66 |
67 |
68 |

69 | Humidity Guage showing %of water saturation 70 |

71 |
72 |
73 | 74 |
75 |
76 |
77 |
78 |

79 | Resistence Guage showing Ohms of resistence 80 |

81 |
82 |
83 | 84 |
85 |
86 |
87 |
88 |

89 | Light Guage showing lux of light penetration 90 |

91 |
92 |
93 | 94 |
95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Cloudboard/Lambdas/connection.js: -------------------------------------------------------------------------------- 1 | //Extra Permission required: SSM - Systemems Manager (search 'system' in inline policys) 2 | 3 | const AWS = require('aws-sdk') 4 | 5 | var mySSM_Client = new AWS.SSM(); //create new client object of System Manager Class 6 | 7 | exports.handler = async (event, context) => { 8 | 9 | console.log(event); 10 | let connectionId = event.requestContext.connectionId; 11 | console.log("myConnectionID is: ", connectionId) 12 | 13 | //-----------------Begin SSM Code 14 | 15 | //https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SSM.html#putParameter-property 16 | var params = { 17 | Name: '', 18 | Value: connectionId, 19 | Overwrite: true //not required but default is False 20 | }; 21 | 22 | //await and promise() stub are not documented but neccessary for function to work - UNFORTUNATELY 23 | var mySSM_request = await mySSM_Client.putParameter(params, function(err, data) { 24 | if (err) console.log(err, err.stack); // an error occurred 25 | else console.log("success: ", data); // successful response 26 | }).promise() 27 | //var mySSM_request = await mySSM_Client.putParameter(params).promise(); //should also work; sans padantic if err else 28 | 29 | console.log("My request: ", mySSM_request) 30 | 31 | //------------------End SSM Code 32 | 33 | const response = { 34 | statusCode: 200, 35 | body: JSON.stringify('Hello from Lambda!'), 36 | }; 37 | return response; //need a response or we get disconnected immediatly 38 | 39 | }; 40 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Cloudboard/Lambdas/sendIoTdata.py: -------------------------------------------------------------------------------- 1 | #Don't forget to add both 'ExecuteAPI' and 'System' (AWS Systems Manger) to your permissions as inline policys for this lambda function 2 | 3 | import json 4 | import boto3 5 | Websocket_HTTPS_URL = "https://" 6 | client = boto3.client("apigatewaymanagementapi", endpoint_url = Websocket_HTTPS_URL) 7 | ssm_Client = boto3.client('ssm') 8 | 9 | def lambda_handler(event, context): 10 | print(event) 11 | response_ssm = ssm_Client.get_parameter(Name='') 12 | print("my stored connection id: ", response_ssm['Parameter']['Value'] ) 13 | connectionId = response_ssm['Parameter']['Value'] #dig into the response blob to get our string cvalue 14 | Test_Message = json.dumps({ "message": "Hello from lambda, hardcoded test message"}) 15 | IoT_Message = json.dumps(event) 16 | #AWS API Gateway API's require 'key=value' arguments 17 | #https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/apigatewaymanagementapi.html#ApiGatewayManagementApi.Client.post_to_connection 18 | response = client.post_to_connection(ConnectionId = connectionId, Data = IoT_Message) 19 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Cloudboard/Plotly/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 16 | 17 |
18 |
19 |
20 |
21 |
22 |
--> 23 |
24 | 25 | 35 | 36 |
37 |
38 |
39 |
40 |
41 | 42 |
43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Cloudboard/README.md: -------------------------------------------------------------------------------- 1 | ![image](https://user-images.githubusercontent.com/16296900/180889616-6d21e390-3486-48a8-b188-83cd2df27606.png) 2 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Cloudboard/S3-Website-Setup-files/CORS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "AllowedHeaders": [ 4 | "Authorization" 5 | ], 6 | "AllowedMethods": [ 7 | "GET" 8 | ], 9 | "AllowedOrigins": [ 10 | "*" 11 | ], 12 | "ExposeHeaders": [], 13 | "MaxAgeSeconds": 4000 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Cloudboard/S3-Website-Setup-files/Public_Bucket_Policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "Publsdg411145d", 6 | "Effect": "Allow", 7 | "Principal": "*", 8 | "Action": [ 9 | "s3:GetObject", 10 | "s3:GetObjectVersion" 11 | ], 12 | "Resource": "arn:aws:s3:::/*" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Cloudboard/S3-Website-Setup-files/README.md: -------------------------------------------------------------------------------- 1 | visualiztions are in Highcharts and Plotly folders 2 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Google_Chart/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Google_Chart/main.js: -------------------------------------------------------------------------------- 1 | 2 | const socket = new WebSocket('wss://.amazonaws.com/production') 3 | 4 | 5 | socket.addEventListener('open', event => { 6 | console.log('WebSocket is connected, now check for your new Connection ID in Cloudwatch and the Parameter Store on AWS') 7 | }) 8 | 9 | 10 | socket.addEventListener('message', event => { 11 | console.log('Your IoTT payload is:', event.data); 12 | 13 | 14 | 15 | var IoT_Payload = JSON.parse(event.data); 16 | console.log("our json object3", IoT_Payload); 17 | 18 | console.log( "humidity is: ", IoT_Payload.humidity); 19 | 20 | 21 | var temperature = IoT_Payload.temperature; 22 | var humidity = IoT_Payload.humidity; 23 | var timestamps = IoT_Payload.timestamps; 24 | 25 | 26 | google.charts.load('current', {packages: ['corechart', 'line']}); 27 | google.charts.setOnLoadCallback(drawBasic); 28 | 29 | function drawBasic() { 30 | 31 | //-----------see about incoming data event from wss 32 | //var IoT_Payload = JSON.parse(data); 33 | // console.log("our json object3", IoT_Payload); 34 | 35 | //console.log( "Humiddxxxxy", IoT_Payload.humidity); 36 | 37 | //------------------------ end incoming event 38 | 39 | 40 | 41 | var theData = new google.visualization.DataTable(); 42 | theData.addColumn('number', 'time'); 43 | theData.addColumn('number', 'temperature'); 44 | theData.addColumn('number', 'humidity'); 45 | 46 | 47 | //the followig three loops convert our strings in into numbers 48 | for(var ts=0; ts 2 | 3 | 4 | 5 | 6 | 7 | 8 | Dashboard 9 | 10 | 11 | 12 |
13 |

Asynchronous IoT Weather Data with AWS WebSockets

14 | 15 |
16 |
17 |

Line Chart

18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | 26 | 44 | 45 | 46 | 47 |
48 | 49 |
50 |
51 | 52 |
53 |

54 | Temperature Gauge with Degrees in Fehr/Cel 55 |

56 |
57 |
58 | 59 | 60 | 61 |
62 |
63 |
64 |

65 | Humidity Guage showing %of water saturation 66 |

67 |
68 |
69 | 70 | 71 |
72 |
73 |
74 |

75 | Epoch/UNIX time, expect many ticks per Second 76 |

77 |
78 |
79 | 80 |
81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/MQTT_Messaging_Lambdas/README.md: -------------------------------------------------------------------------------- 1 | ## These lambdas were developed but not used due to a more simple and more effective solution using the AWS Sytems Manager Paramter Store for saving Connection Id rather than messaging the connection ID between Lambdas via MQTT topics 2 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/MQTT_Messaging_Lambdas/connection.js: -------------------------------------------------------------------------------- 1 | const AWS = require('aws-sdk'); 2 | 3 | const api = new AWS.ApiGatewayManagementApi({ 4 | endpoint: '' 5 | }) 6 | 7 | const iotdata = new AWS.IotData({endpoint: '' }); 8 | 9 | //using asych here and in return/romise function works to establish persistetnt connection 10 | //however it sends twice 11 | //making function nonasych to send topic once by removing async and promise() 12 | //means external websocket connection will never work 13 | 14 | 15 | exports.handler = async (event,context) => { 16 | var connectionId = event.requestContext.connectionId; 17 | console.log("myConnectionvID1: ", connectionId); 18 | console.log("event obj: ", event); 19 | 20 | 21 | var params = { 22 | topic: 'iot/whatever', 23 | payload: JSON.stringify(connectionId), 24 | qos: 0 25 | } 26 | 27 | return { 28 | body: JSON.stringify(await publishMessage(params)) 29 | } 30 | } 31 | 32 | //Publish connection ID to AWS IoT Core 33 | //Message is then consumed by snediotpayload.py python function 34 | //as incoming event under topic iot/# 35 | 36 | const publishMessage = async (params) => { 37 | return new Promise((resolve, reject) => { 38 | iotdata.publish(params, function(err, data){ 39 | if(err){ 40 | console.log(err); 41 | reject(err) 42 | } 43 | else{ 44 | console.log("success?"); 45 | resolve(params) 46 | } 47 | }) 48 | }) 49 | } 50 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/MQTT_Messaging_Lambdas/sendiotpayload.py: -------------------------------------------------------------------------------- 1 | import json 2 | import boto3 3 | 4 | URL = "https://" 5 | client = boto3.client("apigatewaymanagementapi", endpoint_url = URL) 6 | 7 | Global_cId = "" # global varible as empty string, tested to stay resident through invocations, used as connection_Id 8 | 9 | def lambda_handler(event, context): 10 | 11 | default_Message = json.dumps({ "message": "Hello from lambda, no payloads yet"}) 12 | test_payload = json.dumps({"temperature": 55, "humidity": 66, "timestamps":1984}) #works 13 | print(event) 14 | 15 | key = 'humidity' 16 | # python check if key in dict using "in" 17 | if key in json.dumps(event): 18 | print(f"Yes, key: '{key}' exists in dict/json") 19 | event = json.dumps(event) 20 | elif type(event) == str: 21 | print(f'{event} is a string, found connectionID') 22 | global Global_cId #set global varible for connection ID, Global space to stay resident 23 | Global_cId = event 24 | print(f'the: {Global_cId} is a string also, found connectionID') 25 | #set global connection ID from function so it is retained 26 | #set connection ID but not data 27 | #quit() 28 | else: 29 | print(f"I have no idea what: {event} is") 30 | quit() 31 | 32 | response=client.post_to_connection(Data=event, ConnectionId=Global_cId) 33 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Open_Bucket_Policy.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "Publsdg411145d", 6 | "Effect": "Allow", 7 | "Principal": "*", 8 | "Action": [ 9 | "s3:GetObject", 10 | "s3:GetObjectVersion" 11 | ], 12 | "Resource": "arn:aws:s3:::/*" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/PlotlyGraph_Streaming/Device_side_timestamp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/PlotlyGraph_Streaming/Device_side_timestamp/main.js: -------------------------------------------------------------------------------- 1 | const socket = new WebSocket('wss://') 2 | 3 | socket.addEventListener('open', event => { 4 | console.log('WebSocket is connected, now check for your new Connection ID in Cloudwatch and the Parameter Store on AWS') 5 | }) 6 | 7 | 8 | socket.addEventListener('message', event => { 9 | 10 | console.log('Your iot payload is:', event.data); 11 | 12 | var IoT_Payload = JSON.parse(event.data); 13 | console.log("our IoT_Payload temp: ", IoT_Payload.temperature); 14 | 15 | 16 | var dataa = [{ 17 | x: [IoT_Payload.timestamps], 18 | y: [IoT_Payload.temperature], 19 | mode: 'lines', 20 | line: {color: '#ff0033'} 21 | }] 22 | 23 | 24 | var dataa2 = [{ 25 | x: [IoT_Payload.timestamps], 26 | y: [IoT_Payload.humidity], 27 | mode: 'lines', 28 | line: {color: '#80CAF6'} 29 | }] 30 | 31 | 32 | Plotly.plot('graph', dataa); 33 | Plotly.plot('graph', dataa2); 34 | 35 | 36 | var update = { 37 | x: [[IoT_Payload.timestamps]], 38 | y: [[IoT_Payload.temperature]] 39 | } 40 | 41 | var update2 = { 42 | x: [[IoT_Payload.timestamps]], 43 | y: [[IoT_Payload.humidity]] 44 | } 45 | 46 | Plotly.extendTraces('graph', update, [0]) 47 | Plotly.extendTraces('graph', update2, [1]) 48 | 49 | }) //end websocket message function here 50 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/PlotlyGraph_Streaming/Guages&line/README.md: -------------------------------------------------------------------------------- 1 | ![image](https://user-images.githubusercontent.com/16296900/155856267-485d31ca-a2c3-4641-8093-2b0b3de8a4c1.png) 2 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/PlotlyGraph_Streaming/Guages&line/guages.js: -------------------------------------------------------------------------------- 1 | //Designd by Stephen Borsay https://github.com/sborsay 2 | 3 | const socket = new WebSocket('wss://.execute-api.us-east-1.amazonaws.com/production') 4 | 5 | socket.addEventListener('open', event => { 6 | console.log('WebSocket is connected, now check for your new Connection ID in Cloudwatch and the Parameter Store on AWS') 7 | }) 8 | 9 | 10 | socket.addEventListener('message', event => { 11 | 12 | console.log('Your iot payload is:', event.data); 13 | 14 | 15 | var IoT_Payload = JSON.parse(event.data); 16 | console.log("ourr IoT_Payload temp: ", IoT_Payload.temperature); 17 | 18 | 19 | var cc = IoT_Payload.timestamps + (new Date().getTimezoneOffset() * -1); //for timeZone 20 | cc = new Date(cc); 21 | console.log(cc) 22 | 23 | var data = [ 24 | { 25 | domain: { x: [0, 1], y: [0, 1] }, 26 | value: IoT_Payload.temperature, 27 | title: { text: "Temperature" }, 28 | type: "indicator", 29 | mode: "gauge+number", 30 | delta: { reference: 400 }, 31 | gauge: { axis: { range: [null, 130] }, bar: { color: "orange" }} 32 | } 33 | ]; 34 | 35 | var data2 = [ 36 | { 37 | domain: { x: [1, 0], y: [0, 1] }, 38 | value: IoT_Payload.humidity, 39 | title: { text: "Humidity" }, 40 | type: "indicator", 41 | mode: "gauge+number", 42 | delta: { reference: 400 }, 43 | gauge: { axis: { range: [null, 100] }, bar: { color: "darkblue" } } 44 | } 45 | ]; 46 | 47 | 48 | var data3 = [ 49 | { 50 | type: "indicator", 51 | //mode: "number+delta", 52 | mode: "delta", 53 | value: IoT_Payload.timestamps, 54 | title: { text: "Timestamp" }, 55 | //number: { prefix: "Timestamp"}, 56 | //number: { font: { size: 15 }}, 57 | //number : {valueformat:'f'}, 58 | // delta: { position: "top", valueformat:'f' }, 59 | delta : {position: "top",reference:100000, valueformat:'f'}, 60 | font: { 61 | size: [20] 62 | }, 63 | //number: { font: { size: 30 }}, 64 | domain: { x: [0, 1], y: [0, 1] } 65 | } 66 | ]; 67 | 68 | 69 | var layout = { width: 600, height: 300}; 70 | var layout2 = { width: 600, height: 300 }; 71 | //var layout3 = { width: 600, height: 300 }; 72 | var layout3 = { 73 | paper_bgcolor: "white", 74 | width: 600, 75 | height: 300, 76 | margin: { t: 0, b: 0, l: 0, r: 0 } 77 | }; 78 | 79 | 80 | Plotly.newPlot('myDiv', data, layout); 81 | Plotly.newPlot('myDiv2', data2, layout2); 82 | Plotly.newPlot('myDiv3', data3, layout3); 83 | 84 | //begin graph section 85 | 86 | var time = new Date(); 87 | 88 | var dataa = [{ 89 | x: [time], 90 | y: [IoT_Payload.temperature], 91 | mode: 'lines', 92 | line: {color: '#ff0033'}, 93 | name: 'Temperature °' 94 | }] 95 | 96 | var layout4 = { 97 | title: { 98 | text:'Temperature', 99 | font: { 100 | family: 'Courier New, monospace', 101 | size: 36, 102 | color: 'purple' 103 | } 104 | }, 105 | 106 | xaxis: { 107 | title: { 108 | text: "time", 109 | font: { 110 | family: "Courier New, monospace", 111 | size: 18, 112 | color: "#7f7f7f" 113 | } 114 | } 115 | }, 116 | 117 | yaxis: { 118 | title: { 119 | text: "temperature °", 120 | font: { 121 | family: "Courier New, monospace", 122 | size: 18, 123 | color: "#7f7f7f" 124 | } 125 | } 126 | } 127 | } 128 | 129 | 130 | var dataa2 = [{ 131 | x: [time], 132 | y: [IoT_Payload.humidity], 133 | mode: 'lines', 134 | line: {color: '#80CAF6'}, 135 | name: 'Humidity %' 136 | }] 137 | 138 | var layout5 = { 139 | title: { 140 | text:'Humidity', 141 | font: { 142 | family: 'Courier New, monospace', 143 | size: 36, 144 | color: 'purple' 145 | } 146 | }, 147 | 148 | xaxis:{ 149 | title: { 150 | text: "time", 151 | font: { 152 | family: "Courier New, monospace", 153 | size: 18, 154 | color: "#7f7f7f" 155 | } 156 | } 157 | }, 158 | 159 | yaxis: { 160 | title: { 161 | text: "humidity %", 162 | font: { 163 | family: "Courier New, monospace", 164 | size: 18, 165 | color: "#7f7f7f" 166 | } 167 | } 168 | } 169 | } 170 | 171 | 172 | Plotly.plot('myDiv4', dataa, layout4); 173 | Plotly.plot('myDiv5', dataa2, layout5); 174 | 175 | 176 | var update = { 177 | x: [[time]], 178 | y: [[IoT_Payload.temperature]] 179 | } 180 | 181 | var update2 = { 182 | x: [[time]], 183 | y: [[IoT_Payload.humidity]] 184 | } 185 | 186 | Plotly.extendTraces('myDiv4', update, [0]) 187 | Plotly.extendTraces('myDiv5', update2, [1]) 188 | 189 | //end graph section 190 | 191 | }) //end websocket function 192 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/PlotlyGraph_Streaming/Guages&line/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 16 | 17 |
18 |
19 |
20 |
21 |
22 | 23 | 33 | 34 |
35 |
36 |
37 |
38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/PlotlyGraph_Streaming/README.md: -------------------------------------------------------------------------------- 1 | ![image](https://user-images.githubusercontent.com/16296900/153489430-56629932-7226-4a2f-9e54-32d15e64468c.png) 2 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/PlotlyGraph_Streaming/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/PlotlyGraph_Streaming/main.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const socket = new WebSocket('.amazonaws.com/production>') 4 | 5 | socket.addEventListener('open', event => { 6 | console.log('WebSocket is connected, now check for your new Connection ID in Cloudwatch and the Parameter Store on AWS') 7 | }) 8 | 9 | 10 | socket.addEventListener('message', event => { 11 | 12 | console.log('Your iot payload is:', event.data); 13 | 14 | var IoT_Payload = JSON.parse(event.data); 15 | console.log("ourr IoT_Payload temp: ", IoT_Payload.temperature); 16 | 17 | var time = new Date(); 18 | 19 | var dataa = [{ 20 | x: [time], 21 | y: [IoT_Payload.temperature], 22 | mode: 'lines', 23 | line: {color: '#ff0033'} 24 | }] 25 | 26 | 27 | var dataa2 = [{ 28 | x: [time], 29 | y: [IoT_Payload.humidity], 30 | mode: 'lines', 31 | line: {color: '#80CAF6'} 32 | }] 33 | 34 | 35 | Plotly.plot('graph', dataa); 36 | Plotly.plot('graph', dataa2); 37 | 38 | var update = { 39 | x: [[time]], 40 | y: [[IoT_Payload.temperature]] 41 | } 42 | 43 | var update2 = { 44 | x: [[time]], 45 | y: [[IoT_Payload.humidity]] 46 | } 47 | 48 | Plotly.extendTraces('graph', update, [0]) 49 | Plotly.extendTraces('graph', update2, [1]) 50 | 51 | }) //end websocket message function here 52 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/README.md: -------------------------------------------------------------------------------- 1 | ![image](https://user-images.githubusercontent.com/16296900/147861280-7e19ced0-5fbd-4e67-a0ce-aad482d95b01.png) 2 | 3 | ![image](https://user-images.githubusercontent.com/16296900/149595103-97fa3bf6-e784-4713-bea2-7dbb5c1fb626.png) 4 | 5 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/RQS.sql: -------------------------------------------------------------------------------- 1 | SELECT *,timestamp() AS timestamps FROM 'iot/#' 2 | 3 | 4 | //See All AWS IoT Core RQS Functions here: https://docs.aws.amazon.com/iot/latest/developerguide/iot-sql-functions.html 5 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Smoothie_Chart/README.md: -------------------------------------------------------------------------------- 1 | ![image](https://user-images.githubusercontent.com/16296900/149595136-36726808-07c2-4489-aebb-119e04b9f54c.png) 2 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/Smoothie_Chart/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Smoothie Chart 6 | 7 | 8 | 9 | 10 |

Serverless Asynchronous AWS IoT with WebSockets

11 | 12 | 13 | 14 | 64 | 65 |

Return to tutorial

66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/connection_Lambda2.js: -------------------------------------------------------------------------------- 1 | //Extra Permission required: SSM - Systemems Manager (search 'system' in inline policys) 2 | 3 | const AWS = require('aws-sdk') 4 | 5 | var mySSM_Client = new AWS.SSM(); //create new client object of System Manager Class 6 | 7 | exports.handler = async (event, context) => { 8 | 9 | console.log(event); 10 | let connectionId = event.requestContext.connectionId; 11 | console.log("myConnectionID is: ", connectionId) 12 | 13 | //-----------------Begin SSM Code 14 | 15 | //https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SSM.html#putParameter-property 16 | var params = { 17 | Name: '', 18 | Value: connectionId, 19 | Overwrite: true //not required but default is False 20 | }; 21 | 22 | //await and promise() stub are not documented but neccessary for function to work - UNFORTUNATELY 23 | var mySSM_request = await mySSM_Client.putParameter(params, function(err, data) { 24 | if (err) console.log(err, err.stack); // an error occurred 25 | else console.log("success: ", data); // successful response 26 | }).promise() 27 | //var mySSM_request = await mySSM_Client.putParameter(params).promise(); //should also work; sans padantic if err else 28 | 29 | console.log("My request: ", mySSM_request) 30 | 31 | //------------------End SSM Code 32 | 33 | const response = { 34 | statusCode: 200, 35 | body: JSON.stringify('Hello from Lambda!'), 36 | }; 37 | return response; //need a response or we get disconnected immediatly 38 | 39 | }; 40 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Dashboard 9 | 10 | 11 | 12 |
13 |

Asynchronous Weather Data with AWS Websockets

14 | 15 |
16 |
17 |

Line Chart

18 |
19 |
20 |
21 |
22 |
23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/iot_tester.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mqtttopic='iot/ggg' 4 | iterations=10 5 | wait=2 6 | region='us-east-1' 7 | profile='default' 8 | 9 | for (( i = 1; i <=$iterations; i++)) { 10 | 11 | #added these randomizers because old ones didnt generate good numbers 12 | 13 | #Temperature in Fehr 14 | minT=-20 15 | maxT=120 16 | numberT=$(expr $minT + $RANDOM % $maxT) 17 | 18 | #humidity % cannot exceed 100 19 | minH=0 20 | maxH=100 21 | numberH=$(expr $minH + $RANDOM % $maxH) 22 | 23 | #CURRENT_TS=`date +%s` 24 | #DEVICE="P0"$((1 + $RANDOM % 5)) 25 | #FLOW=$(( 60 + $RANDOM % 40 )) 26 | #TEMP=$(( 15 + $RANDOM % 20 )) 27 | #HUMIDITY=$(( 50 + $RANDOM % 40 )) 28 | #VIBRATION=$(( 100 + $RANDOM % 40 )) 29 | temperature=$(($numberT )) 30 | humidity=$(($numberH )) 31 | 32 | # 3% chance of throwing an anomalous temperature reading 33 | #if [ $(($RANDOM % 100)) -gt 97 ] 34 | #then 35 | # echo "Temperature out of range" 36 | # TEMP=$(($TEMP*6)) 37 | #fi 38 | 39 | echo "Publishing message $i/$ITERATIONS to IoT topic $mqtttopic:" 40 | #echo "current_ts: $CURRENT_TS" 41 | #echo "deviceid: $DEVICE" 42 | #echo "flow: $FLOW" 43 | echo "temperature: $temperature" 44 | echo "humidity: $humidity" 45 | #echo "vibration: $VIBRATION" 46 | 47 | #use below for AWS CLI V1 48 | #aws iot-data publish --topic "$mqtttopic" --payload "{\"deviceid\":\"$DEVICE\",\"current_ts\":$CURRENT_TS,\"flow\":$FLOW,\"temp\":$TEMP,\"humidity\":$HUMIDITY,\"vibration\":$VIBRATION}" --profile "$profile" --region "$region" 49 | 50 | #use below for AWS CLI V2 51 | aws iot-data publish --topic "$mqtttopic" --cli-binary-format raw-in-base64-out --payload "{\"temperature\":$temperature,\"humidity\":$humidity}" --profile "$profile" --region "$region" 52 | 53 | sleep $wait 54 | } 55 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/main.js: -------------------------------------------------------------------------------- 1 | let humArr = [], tempArr = [], upArr = []; 2 | let myChart = Highcharts.chart('container1', { 3 | 4 | title: { 5 | text: 'Line chart' 6 | }, 7 | 8 | subtitle: { 9 | text: 'subtitle' 10 | }, 11 | 12 | yAxis: { 13 | title: { 14 | text: 'Value' 15 | } 16 | }, 17 | 18 | xAxis: { 19 | categories: upArr 20 | }, 21 | 22 | legend: { 23 | layout: 'vertical', 24 | align: 'right', 25 | verticalAlign: 'middle' 26 | }, 27 | 28 | plotOptions: { 29 | series: { 30 | label: { 31 | connectorAllowed: false 32 | } 33 | } 34 | }, 35 | series: [{ 36 | name: 'Humdity', 37 | data: [] 38 | }, { 39 | name: 'Temperature', 40 | data: [] 41 | }], 42 | 43 | responsive: { 44 | rules: [{ 45 | condition: { 46 | maxWidth: 500 47 | }, 48 | chartOptions: { 49 | legend: { 50 | layout: 'horizontal', 51 | align: 'center', 52 | verticalAlign: 'bottom' 53 | } 54 | } 55 | }] 56 | } 57 | 58 | }); 59 | 60 | 61 | const socket = new WebSocket('') 62 | 63 | socket.addEventListener('open', event => { 64 | console.log('WebSocket is connected, now check for your new Connection ID in Cloudwatch and the Parameter Store on AWS') 65 | }) 66 | 67 | 68 | 69 | 70 | socket.addEventListener('message', event => { 71 | 72 | console.log('Your iot payload is:', event.data); 73 | drawChart(event.data); 74 | }) 75 | 76 | 77 | 78 | let drawChart = function (data) { 79 | 80 | 81 | var IoT_Payload = JSON.parse(data); 82 | console.log("our json object", IoT_Payload); 83 | //console.log(IoT_Payload.temperature); 84 | 85 | 86 | let { humidity, temperature, timestamps } = IoT_Payload; 87 | 88 | 89 | humArr.push(Number(IoT_Payload.humidity)); 90 | tempArr.push(Number(IoT_Payload.temperature)); 91 | upArr.push(Number(IoT_Payload.timestamps)); 92 | 93 | 94 | myChart.series[0].setData(humArr , true) 95 | myChart.series[1].setData(tempArr , true) 96 | } 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/online_wss_tester_payload.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "message", 3 | "data": { 4 | "temperature": 55, 5 | "humidity": 13 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/result.md: -------------------------------------------------------------------------------- 1 | ![image](https://user-images.githubusercontent.com/16296900/147861271-f24e500a-1483-48b5-970f-eb91a7547e52.png) 2 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/sendiotmessage_lambda2.py: -------------------------------------------------------------------------------- 1 | #Don't forget to add both 'ExecuteAPI' and 'System' (AWS Systems Manger) to your permissions as inline policys for this lambda function 2 | 3 | import json 4 | import boto3 5 | Websocket_HTTPS_URL = "https://" 6 | client = boto3.client("apigatewaymanagementapi", endpoint_url = Websocket_HTTPS_URL) 7 | ssm_Client = boto3.client('ssm') 8 | 9 | 10 | def lambda_handler(event, context): 11 | print(event) 12 | response_ssm = ssm_Client.get_parameter(Name='') 13 | print("my stored connection id: ", response_ssm['Parameter']['Value'] ) 14 | connectionId = response_ssm['Parameter']['Value'] #dig into the response blob to get our string cvalue 15 | Test_Message = json.dumps({ "message": "Hello from lambda, hardcoded test message"}) 16 | IoT_Message = json.dumps(event) 17 | #AWS API Gateway API's require 'key=value' arguments 18 | #https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/apigatewaymanagementapi.html#ApiGatewayManagementApi.Client.post_to_connection 19 | response = client.post_to_connection(ConnectionId = connectionId, Data = IoT_Message) 20 | -------------------------------------------------------------------------------- /Level4_design/3_ Asynchronous_IoT_Intermediate/test_payload.json: -------------------------------------------------------------------------------- 1 | Test For Lambda 2 | 3 | 4 | 5 | { 6 | "temperature": 55, 7 | "humidity": 66, 8 | "timestamps": 12345 9 | } 10 | 11 | 12 | Test for IoT Core (Our RQS adds Timestamps for us) 13 | 14 | { 15 | "temperature": 77, 16 | "humidity": 88 17 | } 18 | 19 | -------------------------------------------------------------------------------- /Level4_design/IMG_4147.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sborsay/Serverless-IoT-on-AWS/902ea767e60062a0e5c067833a9ff9dfd3f40cb7/Level4_design/IMG_4147.jpg -------------------------------------------------------------------------------- /Level4_design/README.md: -------------------------------------------------------------------------------- 1 | ![Capture1](https://user-images.githubusercontent.com/16296900/149591524-47d50b03-8df8-4878-bd6a-ebfc52744ff4.JPG) 2 | 3 | 4 | ![websocketsimproveddiagram](https://user-images.githubusercontent.com/16296900/149591434-3d7aa827-b9d9-4db8-b6a8-20987d2a14f1.JPG) 5 | 6 | 7 | ![websAdv](https://user-images.githubusercontent.com/16296900/149591458-c94bc412-476d-4dbf-a708-2d17c45f8313.JPG) 8 | 9 | -------------------------------------------------------------------------------- /Level4_design/resize15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sborsay/Serverless-IoT-on-AWS/902ea767e60062a0e5c067833a9ff9dfd3f40cb7/Level4_design/resize15.jpg -------------------------------------------------------------------------------- /PubSub_Troubleshooting: -------------------------------------------------------------------------------- 1 | If your data payload coming to or from the device via MQTT PubSUB isn't coming through, it may be your sprintf char buffer 2 | is too large (exceeds 128 chars), issue is discussed here: https://github.com/knolleary/pubsubclient/issues/110 3 | 4 | To view your current buffer size; example below: 5 | 6 | //------------------------------------------ 7 | int bufferSizeTest = snprintf(fakeData, sizeof(fakeData), "{\"uptime\":%lu,\"temp\":%d,\"humid\":%d,\"lattitude\":%2.7f,\"longitude\":%3.7f}", millis() / 1000, t, h, latt, lon ); 8 | 9 | Serial.println('\n'); 10 | Serial.println(bufferSizeTest); 11 | Serial.println('\n'); 12 | //------------------------------------------- 13 | 14 | 15 | to fix this problem see below: 16 | 17 | Arduino-->libraries-->PubSub folder-->src-->PubSubClient.h 18 | 19 | change--> 20 | 21 | // MQTT_MAX_PACKET_SIZE : Maximum packet size 22 | #ifndef MQTT_MAX_PACKET_SIZE 23 | #define MQTT_MAX_PACKET_SIZE 128 24 | #endif 25 | 26 | 27 | to--> 28 | 29 | // MQTT_MAX_PACKET_SIZE : Maximum packet size 30 | #ifndef MQTT_MAX_PACKET_SIZE 31 | #define MQTT_MAX_PACKET_SIZE 512 32 | #endif 33 | -------------------------------------------------------------------------------- /PublicBucket/AWS_CLI_Commands/README.md: -------------------------------------------------------------------------------- 1 | AWS CLI commands for a Public Bucket 2 | 3 | Step 3 – Creating a S3 Bucket from the AWS CLI 4 | Step 4 – Enabling a Static Web Host in the S3 bucket from the AWS CLI 5 | Step 5 – Deleting the S3 Bucket and all files with a single AWS CLI command 6 | 7 | 8 | Step 3 – Creating a S3 Bucket from the AWS CLI 9 | 10 | 11 | When using the CLI the bucket will default to your “home” region in which your AWS CLI is configured. If you make a bucket, as we did in the console, outside your home region, then you will have to use different commands with he ‘s3API’ as I demonstrate below for creating another bucket in us-west-2. 12 | 13 | Create a new bucket with a public ACL 14 | 15 | • Warning: Do not store private information in public buckets, all info is publicly readable 16 | 17 | Create a public bucket with: 18 | 19 | ``` 20 | aws s3api create-bucket --bucket --acl public-read 21 | ``` 22 | 23 | To create a bucket in another (non-home) region: 24 | 25 | ``` 26 | aws s3api create-bucket --bucket --region --create-bucket-configuration LocationConstraint= --acl public-read 27 | 28 | ``` 29 | 30 | Here I create a bucket called “testbucket520cli” in us-west-2 31 | 32 | ![image](https://user-images.githubusercontent.com/16296900/169628656-03c1c4d1-07ca-49eb-927a-95a97ce1b9f9.png) 33 | 34 | 35 | 36 | Check the result in S3 for my new public bucket: 37 | 38 | 39 | ![image](https://user-images.githubusercontent.com/16296900/169628663-ad715a0a-eaf9-4cff-aedd-ac4355ed6d49.png) 40 | 41 | 42 | 43 | Now we need to create and save the following file in the same local folder on your computer that you are using the AWS CLI. So in my case ill navigate to a policys folder on my desktop which contains my policys. 44 | 45 | I will have two bucket policy’s, you can choose either one, they are the same two from the console. One is a public read bucket and the other is a IP limited read bucket policy. Both should be saved as .JSON files: 46 | 47 | 48 | File 1 save as: “public_policy.json” after filling out the ARN expression for your bucket name: 49 | ```JSON 50 | { 51 | "Version": "2012-10-17", 52 | "Statement": [ 53 | { 54 | "Sid": "PublicRead", 55 | "Effect": "Allow", 56 | "Principal": "*", 57 | "Action": "s3:GetObject", 58 | "Resource": "/*" 59 | } 60 | ] 61 | } 62 | ``` 63 | 64 | If you want to use the IP limited policy for extra free security then save as: “ip_limited_policy.json”after filling out the ARN expression for your bucket name: 65 | 66 | ```JSON 67 | { 68 | "Version": "2012-10-17", 69 | "Id": "somethingunique", 70 | "Statement": [ 71 | { 72 | "Sid": "IPAllow", 73 | "Effect": "Allow", 74 | "Principal": "*", 75 | "Action": "s3:GetObject", 76 | "Resource": "arn:aws:s3:::/*", 77 | "Condition": { 78 | "IpAddress": { 79 | "aws:SourceIp": "/24" 80 | } 81 | } 82 | } 83 | ] 84 | } 85 | ``` 86 | 87 | 88 | Upload the file to S3 with the following command 89 | 90 | 91 | ``` 92 | aws s3api put-bucket-policy --region --policy file://ip_limited_policy.json --bucket 93 | ``` 94 | 95 | ![image](https://user-images.githubusercontent.com/16296900/169628708-15b174bb-dfc4-4899-87d3-a71b1f245940.png) 96 | 97 | 98 | The proper response from the AW CLI is no response. Go to your bucketPermissionsbucket Policy and make sure it was installed. 99 | 100 | Now it is time to upload our CORS policy. However, unlike the bucket policy the CORS policy must be in a different format that what we used in the console. Create and save the following file in the same local folder on your computer that you are using the AWS CLI from_ 101 | 102 | File 2 save as:”cors.json” 103 | 104 | ```JSON 105 | { 106 | "CORSRules": [ 107 | { 108 | "AllowedOrigins": ["*"], 109 | "AllowedHeaders": ["Authorization"], 110 | "AllowedMethods": ["GET"], 111 | "MaxAgeSeconds": 4000 112 | } 113 | ] 114 | } 115 | ``` 116 | 117 | Upload the file to S3 with the following command_ 118 | 119 | ``` 120 | aws s3api put-bucket-cors --cors-configuration file://cors.json --bucket --region 121 | ``` 122 | 123 | 124 | ![image](https://user-images.githubusercontent.com/16296900/169628727-18e6550b-128f-4c75-a9b7-3c67783416c1.png) 125 | 126 | 127 | 128 | Step 4 – Enabling a Static Web Host in the S3 bucket from the AWS CLI 129 | 130 | To enable static web hosting on your public bucket, enter the following command: 131 | 132 | aws s3 website s3:// --region --index-document index.html 133 | 134 | ![image](https://user-images.githubusercontent.com/16296900/169628738-8321f964-efae-4e7f-9c72-61f89f68323f.png) 135 | 136 | 137 | 138 | Create and save the following file in the same local folder on your computer that you are using the AWS CLI from: 139 | 140 | File 3 save as: “index.html” 141 | 142 | ```html 143 | 144 | 145 | 146 |

Hello World

147 |

My S3 static webhost, add HTML and JavaScript files as needed

148 | 149 | 150 | ``` 151 | 152 | Upload the index.html file to S3 with the following command 153 | 154 | ``` 155 | aws s3 cp index.html s3:// --region 156 | ``` 157 | 158 | ![image](https://user-images.githubusercontent.com/16296900/169628757-c3fc199f-953d-4edc-9d8b-c3be4aaf81e0.png) 159 | 160 | 161 | There is no multifile upload other than recursive within a folder which would upload all local files. 162 | 163 | 164 | To see your new website for your bucket in your AWS CLI home region navigate to: 165 | 166 | ``` 167 | https://.s3..amazonaws.com/index.html 168 | ``` 169 | ![image](https://user-images.githubusercontent.com/16296900/169628784-8c8eac74-4613-40be-a7aa-45b6bb82c1a3.png) 170 | 171 | 172 | or go to: 173 | 174 | ![image](https://user-images.githubusercontent.com/16296900/169628789-cb53ff72-fd34-4656-876b-27f1f5b7bf55.png) 175 | 176 | 177 | Right click on the Object URL for your website 178 | 179 | Step 5 – Deleting the S3 Bucket and all files with a single AWS CLI command 180 | 181 | 182 | Remove your bucket and all files in your bucket: 183 | 184 | ``` 185 | aws s3 rb s3:// --region --force 186 | ``` 187 | ![image](https://user-images.githubusercontent.com/16296900/169628797-1aebfdd1-527e-4c78-87d7-b0a403824e89.png) 188 | 189 | 190 | This recursively removes all files and then deletes your bucket. 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /PublicBucket/LimitByIPBucketPolicy: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Id": "S3PolicyId1", 4 | "Statement": [ 5 | { 6 | "Sid": "IPAllow", 7 | "Effect": "Allow", 8 | "Principal": "*", 9 | "Action": "s3:GetObject", 10 | "Resource": "arn:aws:s3:::/*", 11 | "Condition": { 12 | "IpAddress": { 13 | "aws:SourceIp": "/24" 14 | } 15 | } 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /PublicBucket/PublicBucketReadPolicy: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "PublicRead", 6 | "Effect": "Allow", 7 | "Principal": "*", 8 | "Action": "s3:GetObject", 9 | "Resource": "arn:aws:s3:::/*" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /PublicBucket/PublicReadCORS: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "AllowedHeaders": [ 4 | "Authorization" 5 | ], 6 | "AllowedMethods": [ 7 | "GET" 8 | ], 9 | "AllowedOrigins": [ 10 | "*" 11 | ], 12 | "ExposeHeaders": [], 13 | "MaxAgeSeconds": 4000 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Serverless-IoT-on-AWS 2 | Code for my Udemy course on AWS Serverless IoT Design www.udemy.com/course/aws-serverless-design-for-iot 3 | -------------------------------------------------------------------------------- /S3lambdaManyFolders.js: -------------------------------------------------------------------------------- 1 | var AWS = require('aws-sdk'); 2 | var s3 = new AWS.S3(); 3 | 4 | exports.handler = (event, context, callbac) => { 5 | var bucketName = '/' + "/" + Date.now(); 6 | var keyName = 'myEvent'; 7 | var content = JSON.stringify(event); 8 | 9 | var params = { Bucket: bucketName, Key: keyName, Body: content }; 10 | 11 | s3.putObject(params, function (err, data) { 12 | if (err) 13 | console.log(err); 14 | else 15 | console.log("Successfully saved object to " + bucketName + "/" + keyName); 16 | }); 17 | }; 18 | -------------------------------------------------------------------------------- /ShadowState/MultiTopics/Republish_SQL: -------------------------------------------------------------------------------- 1 | republish topic Acion from AWS IoT Core 2 | 3 | 4 | 5 | SELECT state.reported.humidity as Alert FROM '$aws/things//shadow/update' WHERE state.reported.humidity > 80 6 | 7 | 8 | redirect topic $aws/things//shadow/update ---> to --> alert/highHumid 9 | -------------------------------------------------------------------------------- /ShadowState/MultiTopics/testPayload.json: -------------------------------------------------------------------------------- 1 | { 2 | "state": { 3 | "reported": { 4 | "uptime": 741, 5 | "temperature": 50, 6 | "humidity": 77, 7 | "message": "empty" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 26 |

goodby from plotly sdb

27 | 28 | -------------------------------------------------------------------------------- /docs/test2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 26 | 27 | -------------------------------------------------------------------------------- /myNode_IoT_Lambda: -------------------------------------------------------------------------------- 1 | // Handler called by IoT Analytics 2 | exports.handler = function handler(event, context, callback) { 3 | 4 | //add timesteamp to incoming data and name it "ServersideTimestamp" 5 | event[0].ServersideTimestamp = Date.now(); 6 | 7 | // Return the data 8 | callback(null, event); 9 | }; 10 | 11 | -------------------------------------------------------------------------------- /myS3lambda.js: -------------------------------------------------------------------------------- 1 | var AWS = require('aws-sdk'); 2 | var s3 = new AWS.S3(); 3 | 4 | exports.handler = (event, context, callbac) => { 5 | var bucketName = '/';//+ "/" + Date.now(); 6 | var keyName = JSON.stringify(Date.now()); 7 | var content = JSON.stringify(event); 8 | 9 | var params = { Bucket: bucketName, Key: keyName, Body: content }; 10 | 11 | s3.putObject(params, function (err, data) { 12 | if (err) 13 | console.log(err); 14 | else 15 | console.log("Successfully saved object to " + bucketName + "/" + keyName); 16 | }); 17 | }; 18 | -------------------------------------------------------------------------------- /security/Add_API_Key: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | //JavaScript code 6 | 7 | 26 | 27 | // Set Header 28 | 29 | var x = new XMLHttpRequest(); 30 | 31 | x.open("GET", "", true); 32 | x.setRequestHeader("x-api-key", APIKeyVar) 33 | -------------------------------------------------------------------------------- /security/BucketPolicy_IPAdress: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Id": "S3Policy_by_IP_Address", 4 | "Statement": [ 5 | { 6 | "Sid": "IPAllow", 7 | "Effect": "Allow", 8 | "Principal": "*", 9 | "Action": "s3:*", 10 | "Resource": "arn:aws:s3:::/*", 11 | "Condition": { 12 | "IpAddress": { 13 | "aws:SourceIp": "/24" 14 | } 15 | } 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /security/Folder_Tagging.md: -------------------------------------------------------------------------------- 1 | //do this command per file you want tagged 2 | -------------------------- 3 | aws s3api put-bucket-tagging --bucket my-bucket --tagging file://tagging.json 4 | 5 | //save file 6 | { 7 | "TagSet": [ 8 | { 9 | "Key": "public", 10 | "Value": "yes" 11 | } 12 | ] 13 | } 14 | ----------------------- 15 | //https://docs.aws.amazon.com/cli/latest/reference/s3api/put-bucket-tagging.html 16 | -------------------------------------------------------------------------------- /security/README.rst: -------------------------------------------------------------------------------- 1 | Mark *italic text* with one asterisk, **bold text** with two. 2 | For ``monospaced text``, use two "backquotes" instead. 3 | -------------------------------------------------------------------------------- /simPub_ESP32.ino: -------------------------------------------------------------------------------- 1 | /* ESP32 AWS IoT 2 | * 3 | * Simplest possible example (that I could come up with) of using an ESP32 with AWS IoT. 4 | * 5 | * Author: Anthony Elder 6 | *Modified by Stephen Borsay for Udemy 7 | * License: Apache License v2 8 | */ 9 | #include 10 | #include // install with Library Manager, I used v2.6.0 11 | 12 | const char* ssid = "YOUR-WIFI-NETWORK"; 13 | const char* password = "YOUR-WIFI-PASSWORD"; 14 | 15 | const char* awsEndpoint = "YOUR-AWS-REGIONAL-ENDPOINT.amazonaws.com"; //found in AWS IoT Core under 'settings' tab 16 | 17 | // Update the two certificate strings below. Paste in the text of your AWS 18 | // device certificate and private key. Add a quote character at the start 19 | // of each line and a backslash, n, quote, space, backslash at the end 20 | // of each line: 21 | 22 | // xxxxxxxxxx-certificate.pem.crt 23 | const char* certificate_pem_crt = \ 24 | 25 | "-----BEGIN CERTIFICATE-----\n" \ 26 | "XXXXXXXXXXXXXXXBAgIVAI7n0dti6sMuimCVANnjs+8i8TUiMA0GCSqGSIb3DQEB\n" \ 27 | "CwUAME0xSzBJBgNVBAsMQkFtYXpvbiBXZWIgU2VydmljZXMgTz1BbWF6b24uY29t\n" \ 28 | "IEluYy4gTD1TZWF0dGxlIFNUPVdhc2hpbmd0b24gQz1VUzAeFw0xOTExMDYxODI1\n" \ 29 | "NDFaFw00OTEyMzEyMzU5NTlaMB4xHDAaBgNVBAMME0FXUyBJb1QgQ2VydGlmaWNh\n" \ 30 | "dGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDRSWA/2xSg/OYOOM6d\n" \ 31 | "2smJIEn3VIgmqCEmrg1+6vdoKBLxgMh194z2Ns83siRG9GPf7+v5oWk0Bu9kDKNl\n" \ 32 | "vquAnBO3+eW1Sgg3JE9SP5utExYGDXud1im6dlG/YbnN8gWCG3W0Abx1vfsiJMP7\n" \ 33 | "yhez8Xp4lb+/fSDH/vbi5IqYLsCsUgSB7hrg0a8zqXa16lq5FjTgUk9CxFDb5V+z\n" \ 34 | "ipXLfcXboisLIAjJMhNXnef+CpM4rQJulf1eZxCV3P9Du8eFpGKx1VFm8/D1pwrh\n" \ 35 | "GJ1N9kFuSWfQHhj+gA383OL7andGE9h2097O4KaqXW9coCZVKv3AjX2WWqczL3uV\n" \ 36 | "6AOdAgMBAAGjYDBeMB8GA1UdIwQYMBaAFOwXufzDBIb6LGYzX9hsuuTkGBggMB0G\n" \ 37 | "A1UdDgQWBBQRfgU2R8TDTFz6lgUra5M/9pFn6jAMBgNVHRMBAf8EAjAAMA4GA1Ud\n" \ 38 | "DwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAQEAB4tmHWDNBu74BDIn+f32c1ED\n" \ 39 | "r+HJjZAVWBwG9v7ubFu/uA+TaHYT+KBaAfB4NfAlOmTpMZN6egLkKfRNNDIA+tAH\n" \ 40 | "PV/QBDZWjCR3YS5sAUIrnSSRzFGRtAFtscYJhJ73Ahhob8H6zXyH2XQRft4663dI\n" \ 41 | "fqMlXsofXS7QH/mhy1zv13su8EaS/UNJRMvB/+ESyEwkQ2BhzpE8TjaBXTkyZuKw\n" \ 42 | "wSBoHO71UqJGhmLkDLp99hKc90KWh08v9jmNBfbTZvIUcCsIz6EhcbfUAg8oBSE0\n" \ 43 | "yuzWG1P4ZwUk70SDcHhDty8GZ9oajrCsLTcv7zrw4aUtfuIFOqXLybqVOCaGOw==\n" \ 44 | "-----END CERTIFICATE-----\n"; 45 | 46 | // xxxxxxxxxx-private.pem.key 47 | const char* private_pem_key = \ 48 | 49 | "-----BEGIN RSA PRIVATE KEY-----\n" \ 50 | "XXXXXXXXXXXXXXXA0UlgP9sUoPzmDjjOndrJiSBJ91SIJqghJq4Nfur3aCgS8YDI\n" \ 51 | "dfeM9jbPN7IkRvRj3+/r+aFpNAbvZAyjZb6rgJwTt/nltUoINyRPUj+brRMWBg17\n" \ 52 | "ndYpunZRv2G5zfIFght1tAG8db37IiTD+8oXs/F6eJW/v30gx/724uSKmC7ArFIE\n" \ 53 | "ge4a4NGvM6l2tepauRY04FJPQsRQ2+Vfs4qVy33F26IrCyAIyTITV53n/gqTOK0C\n" \ 54 | "bpX9XmcQldz/Q7vHhaRisdVRZvPw9acK4RidTfZBbkln0B4Y/oAN/Nzi+2p3RhPY\n" \ 55 | "dtPezuCmql1vXKAmVSr9wI19llqnMy97legDnQIDAQABAoIBAAKo/RkyrqtxK3do\n" \ 56 | "z2+ANWmRyH7lSym6n1k/gxpm4CgpwjvhmCqvr9H9Vlrt37orJw3Undo5a/3mTKqn\n" \ 57 | "4nfLmaBz22hOO9Y3D62rv3pbJp5njLMc/sI905/0GwvksRjmB53kvXVBRGT2ujdv\n" \ 58 | "4jHUGsMFwbnApYRIkd8Y5YhywTQ39gQeC30suTikIlqSbXnT5KJkKcKvsfnAbsx0\n" \ 59 | "bp+7grEYZjkmki7f7KJgJpVWOQBg8JhbRHBFMiIsMQORPDI+NfaHtgUKxBKykCju\n" \ 60 | "gkkf7ljslfMrfLJvB5gGJetoc/ilLS+19O6VZVN3bChpL4OKE+WnsOdjMLPzmfWL\n" \ 61 | "fIoYiAECgYEA9TpqOwUbWuFjAXIU+lTjn/jJCmnkvX3S0tJ9AXxkZBzfN0BlDlMC\n" \ 62 | "XkEfaARLqj05YbvwfikmnXbER9hE3TjHh8uq+Pv8ZzK432X9/kTLuNKksan3sDgP\n" \ 63 | "e94sQmKrNm5cTw2K9fMsk04W9UdkQGG2duZvOINW8iPqtfNy0jj6rZ0CgYEA2nrM\n" \ 64 | "jmoC4MTuhtEDaishocVH5Q3MVCrZWh1QELgu+d7XUFuvpByT1Dw68PAdlcUjQa8t\n" \ 65 | "+1jopKHGEaZ3781dSkFL6fCcpOn4bGBvNKzURt6avj9r4WoK6tzLqymZbr+32eNc\n" \ 66 | "vXgui3fz6V7fZDtE03ixw62qEgLJF+08yhFNzgECgYB7WW+30kDJPNe1EXI13N9G\n" \ 67 | "RziwsUUqf5C9FL1mMvC4XsF0pEJwqxZk3LL0ejypG/SyEXvNqdtPlz7xuHojIH1U\n" \ 68 | "9ABDD1UNf7j4PfA9ptMmW2YWK514GSrIrp9qoQDn9ykdZn2Aa1n/mmb353oo3D2Q\n" \ 69 | "nyZQsdfZInHcJeGalqiZDQKBgQDZ6N0ZtlbEhOc7hEEZpYdX6IL6zLZdxJchMFdp\n" \ 70 | "Nat1AXRT6/7VesNfTeuj4HpBpWyy2NzN8zGm8suxUw4RGg3QQCxNWvWB7vMedVi1\n" \ 71 | "eyQGw4Qn+O3K2I+nDS3+u/ES6xmesw0O1U3nQW7/9uZs/Eh7e8gh2Zble+3CdZbK\n" \ 72 | "HFQ0AQKBgQCQWrO4PaQQIZ/ZPi9/lKZLRHAb30gx1Qpgpv2pbpxVyIKRfOdDvpHg\n" \ 73 | "Fp+icoIMvHcPoJPz13QYujADzmKpLviKYXDDojJ6sCrPmieV0wAEsF19zbOkMZgr\n" \ 74 | "guGf0uCCv7CpEoRvaVUAX12/Kp9iA03b5hc3hTqBTMSKirdRlouugA==\n" \ 75 | "-----END RSA PRIVATE KEY-----\n"; 76 | 77 | /* root CA can be downloaded in: 78 | https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem 79 | */ 80 | const char* rootCA = \ 81 | "-----BEGIN CERTIFICATE-----\n" \ 82 | "MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF\n" \ 83 | "ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n" \ 84 | "b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL\n" \ 85 | "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv\n" \ 86 | "b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj\n" \ 87 | "ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM\n" \ 88 | "9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw\n" \ 89 | "IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6\n" \ 90 | "VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L\n" \ 91 | "93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm\n" \ 92 | "jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\n" \ 93 | "AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA\n" \ 94 | "A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI\n" \ 95 | "U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs\n" \ 96 | "N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv\n" \ 97 | "o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU\n" \ 98 | "5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy\n" \ 99 | "rqXRfboQnoZsG4q5WTP468SQvvG5\n" \ 100 | "-----END CERTIFICATE-----\n"; 101 | 102 | 103 | WiFiClientSecure wiFiClient; 104 | void msgReceived(char* topic, byte* payload, unsigned int len); 105 | PubSubClient pubSubClient(awsEndpoint, 8883, msgReceived, wiFiClient); 106 | 107 | void setup() { 108 | Serial.begin(115200); delay(50); Serial.println(); 109 | Serial.println("ESP32 AWS GPS Weather Example by SDB for Udemy"); 110 | Serial.printf("SDK version: %s\n", ESP.getSdkVersion()); 111 | 112 | Serial.print("Connecting to "); Serial.print(ssid); 113 | WiFi.begin(ssid, password); 114 | WiFi.waitForConnectResult(); 115 | Serial.print(", WiFi connected, IP address: "); Serial.println(WiFi.localIP()); 116 | 117 | wiFiClient.setCACert(rootCA); 118 | wiFiClient.setCertificate(certificate_pem_crt); 119 | wiFiClient.setPrivateKey(private_pem_key); 120 | } 121 | 122 | unsigned long lastPublish; 123 | int msgCount; 124 | 125 | void loop() { 126 | 127 | pubSubCheckConnect(); 128 | 129 | //If you need to increase buffer size, then you need to change MQTT_MAX_PACKET_SIZE in PubSubClient.h 130 | char fakeData[128]; 131 | 132 | int t = random(30,95); //fake number range, adjust as you like 133 | int h = random(50,95); 134 | 135 | snprintf(fakeData, sizeof(fakeData),"{\"temperature\":%d,\"humidity\":%d}", t, h); 136 | 137 | if (millis() - lastPublish > 10000) { 138 | boolean rc = pubSubClient.publish("outTopic", fakeData); 139 | Serial.print("Published, rc="); Serial.print( (rc ? "OK: " : "FAILED: ") ); 140 | Serial.println(fakeData); 141 | lastPublish = millis(); 142 | } 143 | } 144 | 145 | void msgReceived(char* topic, byte* payload, unsigned int length) { 146 | Serial.print("Message received on "); Serial.print(topic); Serial.print(": "); 147 | for (int i = 0; i < length; i++) { 148 | Serial.print((char)payload[i]); 149 | } 150 | Serial.println(); 151 | } 152 | 153 | void pubSubCheckConnect() { 154 | if ( ! pubSubClient.connected()) { 155 | Serial.print("PubSubClient connecting to: "); Serial.print(awsEndpoint); 156 | while ( ! pubSubClient.connected()) { 157 | Serial.print("."); 158 | pubSubClient.connect("ESPthingXXXX"); 159 | delay(1000); 160 | } 161 | Serial.println(" connected"); 162 | pubSubClient.subscribe("inTopic"); 163 | } 164 | pubSubClient.loop(); 165 | } 166 | -------------------------------------------------------------------------------- /troubleshooting_device_connections: -------------------------------------------------------------------------------- 1 | 2 | 3 | Troubleshooting ESP8266 and ESP32 connection issues. 4 | 5 | 6 | 1A. Make sure you are on a 2.4GHz network not 5GHz, the device only communicates at 2.4GHz 7 | 8 | 1B. Make sure the your device AWS endpoint region matches the current AWS region in your console on the browser 9 | 10 | 1C. Use the 'ATS' AWS endpoint from IoT Core--> Settings or: aws iot describe-endpoint --endpoint-type iot:Data-ATS 11 | 12 | 2. Make sure port 8883 isn't being blocked by your network admin, this is the port that MQTT(s) traditionally communicates, 13 | AWS IoT Core requires you send MQTT data over secure port 8883 or 443 14 | 15 | 3. Make sure your onboard device certificates match your AWS IoT Core region, the x509 should be fungible between regions 16 | 17 | 4. Make sure you attached an AWS IoT Policy to your security certificates. If you have not you will see the connection on the 18 | monitor tab but no data will appear on the MQTT test console. 19 | 20 | 5. Don't exceed your Char, sprintf, or snprintf buffer. MQTT requires payloads get sent by time and size over cycles. 21 | if you overload the buffer it may not transmit or receive the payload. To solve this issue for large payloads you 22 | can also increase the size of your MQTT BUffer by changing the value of MQTT_MAX_PACKET_SIZE in PubSubClient.h from 128 to 512. 23 | to solve this issue. This bigger payload allocation will allow longer variable names to transmit. If you use the alternate ESP32 24 | In the alternate ESP32 sketch on my github the buffer is set to 512 automatically by this line: MQTTClient client = MQTTClient(512); 25 | This alternate ESP32 sketch uses a different PubSub/MQTT library but operates fundamentally in the same way 26 | 27 | 6. If you aren't receiving your devices payload under your subscription topic in AWS IoT Core in the "test" tab, 28 | then go to the "Monitor" tab and see if your device is even connecting. Often a device is actually connecting, 29 | but the payload isn't being received, the reason for this is usually a problem with your device certificates. 30 | The device will connect but the payload wont pass through if your device certificates aren't exactly correct. 31 | If your device isn't even ahowing up in the Monitor then it is likely a hardware issue not a certificate issue. 32 | Confirm you are using the correct virtulization package or board manager for your device. 33 | 34 | ---------------------------------------------------------------------------- 35 | Some older or cheaper ESP32 Boards: 36 | 37 | Connecting........_____....._____....._____....._____....._____....._____....._____....._____....._____....._____ 38 | A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header 39 | 40 | Solution: 41 | while connecting holding down the Boot/EN button for one second initiates the firmware download mode 42 | BOOT = FLASH: if you hold it down and press the EN/RST, your ESP32 will restart in flashing/uploading mode 43 | Do not press the RESET Button 44 | --------------------------------------------------------------------------------