├── .DS_Store ├── Chapter#10 Project#5 Making homes smarter by Voice Assistant ├── Voice_Controlled_Smart_Lamp_may13a.zip └── WS2812_Testing │ └── WS2812_Testing.ino ├── Chapter#11 Implementing Arduino IoT Cloud Scheduler and Over-the-Air Features └── Cloud_Scheduler_may22a.zip ├── Chapter#12 Project#6 Tracking and notifying Your Heart Rate ├── .DS_Store ├── GettingStartedProject │ └── GettingStartedProject.ino └── PulseSensor_BPM_Alternative │ └── PulseSensor_BPM_Alternative.ino ├── Chapter#4 Project#1 Sensing and Monitoring the Air for Clean Environment ├── .DS_Store └── Sense_the_Environment_feb24a │ ├── ReadMe.adoc │ ├── Sense_the_Environment_feb24a.ino │ ├── arduino_secrets.h │ ├── sketch.json │ └── thingProperties.h ├── Chapter#5 Project#2 A portable thing tracker using MKR NB 1500 ├── A_portable_thing_tracker_using_MKR_GSM1400_apr07a.zip └── MKR-1400-NEO-6M-GPS-Module │ └── MKR-1400-NEO-6M-GPS-Module.ino ├── Chapter#6Project#3 A remote alarming application with LoRaWAN ├── A_remote_asset_tracking_using_LoRaWAN_aug30a.zip └── MKR-WAN-1300-NEO-6M-GPS-Module │ └── MKR-WAN-1300-NEO-6M-GPS-Module │ └── MKR-WAN-1300-NEO-6M-GPS-Module.ino ├── Chapter#7 Enabling different Things to talk to each other └── Indoor_Device_MKR_Wi-Fi_1010_sep07a.zip ├── Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript ├── .DS_Store ├── dashboard │ ├── create-dashboard.js │ ├── delete-dashboard.js │ ├── list-dashboard.js │ ├── show-dashboard.js │ └── update-dashboard.js ├── device │ ├── create-device.js │ ├── delete-device.js │ ├── list-device.js │ ├── properties-device.js │ ├── show-device.js │ ├── timeseries-prop-device.js │ └── update-device.js ├── getset │ ├── get-prop.js │ └── set-prop.js ├── node_modules.zip ├── package-lock.json ├── package.json ├── properties │ ├── create-property.js │ ├── delete-property.js │ ├── list-property.js │ ├── show-property.js │ └── update-property.js ├── start │ └── main.js └── thing │ ├── create-sketch-thing.js │ ├── create-thing.js │ ├── delete-thing.js │ ├── list-thing.js │ ├── show-thing.js │ └── update-thing.js ├── Chapter#9 Project#4 Collecting Data from soil and Environment for Smart Farming ├── .DS_Store ├── AgriStack_mar05a.zip ├── DS18B20-Calibration │ └── DS18B20-Calibration.ino └── Soil-Moisture-Calibration │ └── Soil-Moisture-Calibration.ino ├── LICENSE └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Arduino-IoT-Cloud-for-Developers/7573bbb2039ca406b20e6718489c16b6e6792dff/.DS_Store -------------------------------------------------------------------------------- /Chapter#10 Project#5 Making homes smarter by Voice Assistant/Voice_Controlled_Smart_Lamp_may13a.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Arduino-IoT-Cloud-for-Developers/7573bbb2039ca406b20e6718489c16b6e6792dff/Chapter#10 Project#5 Making homes smarter by Voice Assistant/Voice_Controlled_Smart_Lamp_may13a.zip -------------------------------------------------------------------------------- /Chapter#10 Project#5 Making homes smarter by Voice Assistant/WS2812_Testing/WS2812_Testing.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define LED_PIN D3 4 | 5 | // How many NeoPixels are attached to the Arduino? 6 | #define LED_COUNT 16 7 | 8 | // Declare our NeoPixel strip object: 9 | Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); 10 | 11 | void setup() { 12 | 13 | strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) 14 | strip.show(); // Turn OFF all pixels ASAP 15 | strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255) 16 | } 17 | 18 | // loop() function -- runs repeatedly as long as board is on --------------- 19 | void loop() { 20 | 21 | for(int i=0; i Threshold){ // If the signal is above "550", then "turn-on" Arduino's on-Board LED. 49 | digitalWrite(LED,HIGH); 50 | } else { 51 | digitalWrite(LED,LOW); // Else, the sigal must be below "550", so "turn-off" this LED. 52 | } 53 | 54 | 55 | delay(10); 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /Chapter#12 Project#6 Tracking and notifying Your Heart Rate/PulseSensor_BPM_Alternative/PulseSensor_BPM_Alternative.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Sketch to handle each sample read from a PulseSensor. 3 | Typically used when you don't want to use interrupts 4 | to read PulseSensor voltages. 5 | 6 | Here is a link to the tutorial that discusses this code 7 | https://pulsesensor.com/pages/getting-advanced 8 | 9 | Copyright World Famous Electronics LLC - see LICENSE 10 | Contributors: 11 | Joel Murphy, https://pulsesensor.com 12 | Yury Gitman, https://pulsesensor.com 13 | Bradford Needham, @bneedhamia, https://bluepapertech.com 14 | 15 | Licensed under the MIT License, a copy of which 16 | should have been included with this software. 17 | 18 | This software is not intended for medical use. 19 | */ 20 | 21 | 22 | #define USE_ARDUINO_INTERRUPTS false 23 | #include 24 | 25 | const int OUTPUT_TYPE = SERIAL_PLOTTER; 26 | 27 | 28 | const int PULSE_INPUT = A1; 29 | const int PULSE_BLINK = 10; 30 | const int PULSE_FADE = 5; 31 | const int THRESHOLD = 3450; // Adjust this number to avoid noise when idle 32 | 33 | byte samplesUntilReport; 34 | const byte SAMPLES_PER_SERIAL_SAMPLE = 10; 35 | 36 | /* 37 | All the PulseSensor Playground functions. 38 | */ 39 | PulseSensorPlayground pulseSensor; 40 | 41 | void setup() { 42 | Serial.begin(115200); 43 | pinMode(PULSE_INPUT,INPUT); 44 | // Configure the PulseSensor manager. 45 | pulseSensor.analogInput(PULSE_INPUT); 46 | pulseSensor.blinkOnPulse(PULSE_BLINK); 47 | pulseSensor.fadeOnPulse(PULSE_FADE); 48 | 49 | pulseSensor.setSerial(Serial); 50 | pulseSensor.setOutputType(OUTPUT_TYPE); 51 | pulseSensor.setThreshold(THRESHOLD); 52 | 53 | // Skip the first SAMPLES_PER_SERIAL_SAMPLE in the loop(). 54 | samplesUntilReport = SAMPLES_PER_SERIAL_SAMPLE; 55 | 56 | // Now that everything is ready, start reading the PulseSensor signal. 57 | if (!pulseSensor.begin()) { 58 | /* 59 | PulseSensor initialization failed, 60 | likely because our Arduino platform interrupts 61 | aren't supported yet. 62 | 63 | If your Sketch hangs here, try changing USE_PS_INTERRUPT to false. 64 | */ 65 | for(;;) { 66 | // Flash the led to show things didn't work. 67 | digitalWrite(PULSE_BLINK, LOW); 68 | delay(50); 69 | digitalWrite(PULSE_BLINK, HIGH); 70 | delay(50); 71 | } 72 | } 73 | } 74 | 75 | void loop() { 76 | 77 | if (pulseSensor.sawNewSample()) { 78 | /* 79 | Every so often, send the latest Sample. 80 | We don't print every sample, because our baud rate 81 | won't support that much I/O. 82 | */ 83 | if (--samplesUntilReport == (byte) 0) { 84 | samplesUntilReport = SAMPLES_PER_SERIAL_SAMPLE; 85 | 86 | //pulseSensor.outputSample(); 87 | 88 | /* 89 | At about the beginning of every heartbeat, 90 | report the heart rate and inter-beat-interval. 91 | */ 92 | if (pulseSensor.sawStartOfBeat()) { 93 | pulseSensor.outputBeat(); 94 | Serial.print(pulseSensor.getBeatsPerMinute()); 95 | Serial.println(" bpm"); 96 | } 97 | 98 | } 99 | 100 | /******* 101 | Here is a good place to add code that could take up 102 | to a millisecond or so to run. 103 | *******/ 104 | } 105 | 106 | /****** 107 | Don't add code here, because it could slow the sampling 108 | from the PulseSensor. 109 | ******/ 110 | } 111 | -------------------------------------------------------------------------------- /Chapter#4 Project#1 Sensing and Monitoring the Air for Clean Environment/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Arduino-IoT-Cloud-for-Developers/7573bbb2039ca406b20e6718489c16b6e6792dff/Chapter#4 Project#1 Sensing and Monitoring the Air for Clean Environment/.DS_Store -------------------------------------------------------------------------------- /Chapter#4 Project#1 Sensing and Monitoring the Air for Clean Environment/Sense_the_Environment_feb24a/ReadMe.adoc: -------------------------------------------------------------------------------- 1 | :Author: Muhammad Afzal 2 | :Email: 3 | :Date: 24/02/2023 4 | :Revision: version# 5 | :License: Public Domain 6 | 7 | = Project: {Sense the Environment} 8 | 9 | Describe your project 10 | 11 | == Step 1: Installation 12 | Please describe the steps to install this project. 13 | 14 | For example: 15 | 16 | 1. Open this file 17 | 2. Edit as you like 18 | 3. Release to the World! 19 | 20 | == Step 2: Assemble the circuit 21 | 22 | Assemble the circuit following the diagram layout.png attached to the sketch 23 | 24 | == Step 3: Load the code 25 | 26 | Upload the code contained in this sketch on to your board 27 | 28 | === Folder structure 29 | 30 | .... 31 | sketch123 => Arduino sketch folder 32 | ├── sketch123.ino => main Arduino file 33 | ├── schematics.png => (optional) an image of the required schematics 34 | ├── layout.png => (optional) an image of the layout 35 | └── ReadMe.adoc => this file 36 | .... 37 | 38 | === License 39 | This project is released under a {License} License. 40 | 41 | === Contributing 42 | To contribute to this project please contact: 43 | 44 | === BOM 45 | Add the bill of the materials you need for this project. 46 | 47 | |=== 48 | | ID | Part name | Part number | Quantity 49 | | R1 | 10k Resistor | 1234-abcd | 10 50 | | L1 | Red LED | 2345-asdf | 5 51 | | A1 | Arduino Zero | ABX00066 | 1 52 | |=== 53 | 54 | 55 | === Help 56 | This document is written in the _AsciiDoc_ format, a markup language to describe documents. 57 | If you need help you can search the http://www.methods.co.nz/asciidoc[AsciiDoc homepage] 58 | or consult the http://powerman.name/doc/asciidoc[AsciiDoc cheatsheet] 59 | -------------------------------------------------------------------------------- /Chapter#4 Project#1 Sensing and Monitoring the Air for Clean Environment/Sense_the_Environment_feb24a/Sense_the_Environment_feb24a.ino: -------------------------------------------------------------------------------- 1 | #include "arduino_secrets.h" 2 | /* 3 | Sketch generated by the Arduino IoT Cloud Thing "Untitled 2" 4 | https://create.arduino.cc/cloud/things/91c90962-56b6-4094-abe0-1b5ad4828721 5 | 6 | Arduino IoT Cloud Variables description 7 | 8 | The following variables are automatically generated and updated when changes are made to the Thing 9 | 10 | int airQuality; 11 | int temperature; 12 | CloudRelativeHumidity humidity; 13 | 14 | Variables which are marked as READ/WRITE in the Cloud Thing will also have functions 15 | which are called when their values are changed from the Dashboard. 16 | These functions are generated with the Thing and added at the end of this sketch. 17 | */ 18 | 19 | #include "thingProperties.h" 20 | #include 21 | #include 22 | #include 23 | 24 | #define DHTPIN 5 // Digital pin connected to the DHT sensor 25 | #define DHTTYPE DHT11 // Write DHT11 or DHT22 According to your Sensor 26 | 27 | DHT_Unified dht(DHTPIN, DHTTYPE); 28 | uint32_t delayMS; 29 | unsigned long previousMillis = 0; 30 | const long interval = 300000; //milliseconds 31 | 32 | void setup() { 33 | // Initialize serial and wait for port to open: 34 | Serial.begin(9600); 35 | // This delay gives the chance to wait for a Serial Monitor without blocking if none is found 36 | delay(1500); 37 | 38 | // Defined in thingProperties.h 39 | initProperties(); 40 | 41 | // Connect to Arduino IoT Cloud 42 | ArduinoCloud.begin(ArduinoIoTPreferredConnection); 43 | 44 | /* 45 | The following function allows you to obtain more information 46 | related to the state of network and IoT Cloud connection and errors 47 | the higher number the more granular information you’ll get. 48 | The default is 0 (only errors). 49 | Maximum is 4 50 | */ 51 | setDebugMessageLevel(2); 52 | ArduinoCloud.printDebugInfo(); 53 | 54 | dht.begin(); //Init DHT 55 | 56 | Serial.println(F("DHTxx Unified Sensor Example")); 57 | // Print temperature sensor details. 58 | sensor_t sensor; 59 | dht.temperature().getSensor(&sensor); 60 | Serial.println(F("------------------------------------")); 61 | Serial.println(F("Temperature Sensor")); 62 | Serial.print (F("Sensor Type: ")); Serial.println(sensor.name); 63 | Serial.print (F("Driver Ver: ")); Serial.println(sensor.version); 64 | Serial.print (F("Unique ID: ")); Serial.println(sensor.sensor_id); 65 | Serial.print (F("Max Value: ")); Serial.print(sensor.max_value); Serial.println(F("°C")); 66 | Serial.print (F("Min Value: ")); Serial.print(sensor.min_value); Serial.println(F("°C")); 67 | Serial.print (F("Resolution: ")); Serial.print(sensor.resolution); Serial.println(F("°C")); 68 | Serial.println(F("------------------------------------")); 69 | // Print humidity sensor details. 70 | dht.humidity().getSensor(&sensor); 71 | Serial.println(F("Humidity Sensor")); 72 | Serial.print (F("Sensor Type: ")); Serial.println(sensor.name); 73 | Serial.print (F("Driver Ver: ")); Serial.println(sensor.version); 74 | Serial.print (F("Unique ID: ")); Serial.println(sensor.sensor_id); 75 | Serial.print (F("Max Value: ")); Serial.print(sensor.max_value); Serial.println(F("%")); 76 | Serial.print (F("Min Value: ")); Serial.print(sensor.min_value); Serial.println(F("%")); 77 | Serial.print (F("Resolution: ")); Serial.print(sensor.resolution); Serial.println(F("%")); 78 | Serial.println(F("------------------------------------")); 79 | // Set delay between sensor readings based on sensor details. 80 | delayMS = sensor.min_delay / 1000; 81 | STHAM(); 82 | } 83 | 84 | void loop() { 85 | ArduinoCloud.update(); 86 | 87 | unsigned long currentMillis = millis(); 88 | if (currentMillis - previousMillis >= interval) { 89 | STHAM(); 90 | previousMillis = currentMillis; 91 | } 92 | 93 | } 94 | 95 | void STHAM(){ 96 | // Get temperature event and print its value. 97 | sensors_event_t event; 98 | dht.temperature().getEvent(&event); 99 | if (isnan(event.temperature)) { 100 | Serial.println(F("Error reading temperature!")); 101 | //Assign temperature value 0 to Cloud Variable 102 | temperature=0; 103 | } 104 | else { 105 | Serial.print(F("Temperature: ")); 106 | Serial.print(event.temperature); 107 | Serial.println(F("°C")); 108 | //Assign temperature value to Cloud Variable 109 | temperature=event.temperature; 110 | } 111 | 112 | // Get humidity event and print its value. 113 | dht.humidity().getEvent(&event); 114 | if (isnan(event.relative_humidity)) { 115 | Serial.println(F("Error reading humidity!")); 116 | //Assign humidity value 0 to Cloud Variable 117 | humidity=0; 118 | } 119 | else { 120 | Serial.print(F("Humidity: ")); 121 | Serial.print(event.relative_humidity); 122 | Serial.println(F("%")); 123 | //Assign humidity value to Cloud Variable 124 | humidity=event.relative_humidity; 125 | } 126 | 127 | //Assign AirQuality value to Cloud Variable 128 | airQuality=analogRead(A0); 129 | Serial.print("Air Quality="); 130 | Serial.print(airQuality); 131 | Serial.println("%"); 132 | } 133 | 134 | 135 | /* 136 | Since AirQuality is READ_WRITE variable, onAirQualityChange() is 137 | executed every time a new value is received from IoT Cloud. 138 | */ 139 | void onAirQualityChange() { 140 | // Add your code here to act upon AirQuality change 141 | } 142 | /* 143 | Since Temperature is READ_WRITE variable, onTemperatureChange() is 144 | executed every time a new value is received from IoT Cloud. 145 | */ 146 | void onTemperatureChange() { 147 | // Add your code here to act upon Temperature change 148 | } 149 | /* 150 | Since Humidity is READ_WRITE variable, onHumidityChange() is 151 | executed every time a new value is received from IoT Cloud. 152 | */ 153 | void onHumidityChange() { 154 | // Add your code here to act upon Humidity change 155 | } 156 | 157 | 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /Chapter#4 Project#1 Sensing and Monitoring the Air for Clean Environment/Sense_the_Environment_feb24a/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | #define SECRET_SSID "" 2 | #define SECRET_OPTIONAL_PASS "" 3 | #define SECRET_DEVICE_KEY "" 4 | -------------------------------------------------------------------------------- /Chapter#4 Project#1 Sensing and Monitoring the Air for Clean Environment/Sense_the_Environment_feb24a/sketch.json: -------------------------------------------------------------------------------- 1 | { 2 | "cpu": { 3 | "fqbn": "esp8266:esp8266:d1_mini:xtal=80,vt=flash,exception=disabled,eesz=4M,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=921600", 4 | "name": "ESP8266 LOLIN(WEMOS) D1 R2 \u0026 mini", 5 | "type": "serial" 6 | }, 7 | "secrets": [ 8 | { 9 | "name": "SECRET_DEVICE_KEY", 10 | "value": "" 11 | }, 12 | { 13 | "name": "SECRET_OPTIONAL_PASS", 14 | "value": "" 15 | }, 16 | { 17 | "name": "SECRET_SSID", 18 | "value": "" 19 | } 20 | ], 21 | "included_libs": [] 22 | } -------------------------------------------------------------------------------- /Chapter#4 Project#1 Sensing and Monitoring the Air for Clean Environment/Sense_the_Environment_feb24a/thingProperties.h: -------------------------------------------------------------------------------- 1 | // Code generated by Arduino IoT Cloud, DO NOT EDIT. 2 | 3 | #include 4 | #include 5 | 6 | const char DEVICE_LOGIN_NAME[] = "ef63111f-72bb-4826-84bb-02093d4d85f1"; 7 | 8 | const char SSID[] = SECRET_SSID; // Network SSID (name) 9 | const char PASS[] = SECRET_OPTIONAL_PASS; // Network password (use for WPA, or use as key for WEP) 10 | const char DEVICE_KEY[] = SECRET_DEVICE_KEY; // Secret device password 11 | 12 | 13 | int airQuality; 14 | int temperature; 15 | CloudRelativeHumidity humidity; 16 | 17 | void initProperties(){ 18 | 19 | ArduinoCloud.setBoardId(DEVICE_LOGIN_NAME); 20 | ArduinoCloud.setSecretDeviceKey(DEVICE_KEY); 21 | ArduinoCloud.addProperty(airQuality, READ, ON_CHANGE, NULL); 22 | ArduinoCloud.addProperty(temperature, READ, ON_CHANGE, NULL); 23 | ArduinoCloud.addProperty(humidity, READ, ON_CHANGE, NULL); 24 | 25 | } 26 | 27 | WiFiConnectionHandler ArduinoIoTPreferredConnection(SSID, PASS); 28 | -------------------------------------------------------------------------------- /Chapter#5 Project#2 A portable thing tracker using MKR NB 1500/A_portable_thing_tracker_using_MKR_GSM1400_apr07a.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Arduino-IoT-Cloud-for-Developers/7573bbb2039ca406b20e6718489c16b6e6792dff/Chapter#5 Project#2 A portable thing tracker using MKR NB 1500/A_portable_thing_tracker_using_MKR_GSM1400_apr07a.zip -------------------------------------------------------------------------------- /Chapter#5 Project#2 A portable thing tracker using MKR NB 1500/MKR-1400-NEO-6M-GPS-Module/MKR-1400-NEO-6M-GPS-Module.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TinyGPSPlus gps;//This is the GPS object that will pretty much do all the grunt work with the NMEA data 4 | void setup() 5 | { 6 | 7 | Serial.begin(9600);//This opens up communications to the Serial monitor in the Arduino IDE 8 | Serial1.begin(9600);//This opens up communications to the GPS 9 | Serial.println("GPS Start");//Just show to the monitor that the sketch has started 10 | } 11 | 12 | void loop() 13 | { 14 | 15 | while(Serial1.available()>0)//While there are characters to come from the GPS 16 | { 17 | gps.encode(Serial1.read());//This feeds the serial NMEA data into the library one char at a time 18 | } 19 | if(gps.location.isUpdated())//This will pretty much be fired all the time anyway but will at least reduce it to only after a package of NMEA data comes in 20 | { 21 | //Get the latest info from the gps object which it derived from the data sent by the GPS unit 22 | Serial.println("Satellite Count:"); 23 | Serial.println(gps.satellites.value()); 24 | Serial.println("Latitude:"); 25 | Serial.println(gps.location.lat(), 6); 26 | Serial.println("Longitude:"); 27 | Serial.println(gps.location.lng(), 6); 28 | Serial.println("Speed MPH:"); 29 | Serial.println(gps.speed.mph()); 30 | Serial.println("Altitude Feet:"); 31 | Serial.println(gps.altitude.feet()); 32 | Serial.println(""); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Chapter#6Project#3 A remote alarming application with LoRaWAN/A_remote_asset_tracking_using_LoRaWAN_aug30a.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Arduino-IoT-Cloud-for-Developers/7573bbb2039ca406b20e6718489c16b6e6792dff/Chapter#6Project#3 A remote alarming application with LoRaWAN/A_remote_asset_tracking_using_LoRaWAN_aug30a.zip -------------------------------------------------------------------------------- /Chapter#6Project#3 A remote alarming application with LoRaWAN/MKR-WAN-1300-NEO-6M-GPS-Module/MKR-WAN-1300-NEO-6M-GPS-Module/MKR-WAN-1300-NEO-6M-GPS-Module.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TinyGPSPlus gps;//This is the GPS object that will pretty much do all the grunt work with the NMEA data 4 | void setup() 5 | { 6 | 7 | Serial.begin(9600);//This opens up communications to the Serial monitor in the Arduino IDE 8 | Serial1.begin(9600);//This opens up communications to the GPS 9 | Serial.println("GPS Start");//Just show to the monitor that the sketch has started 10 | } 11 | 12 | void loop() 13 | {x 14 | 15 | while(Serial1.available()>0)//While there are characters to come from the GPS 16 | { 17 | gps.encode(Serial1.read());//This feeds the serial NMEA data into the library one char at a time 18 | } 19 | if(gps.location.isUpdated())//This will pretty much be fired all the time anyway but will at least reduce it to only after a package of NMEA data comes in 20 | { 21 | //Get the latest info from the gps object which it derived from the data sent by the GPS unit 22 | Serial.println("Satellite Count:"); 23 | Serial.println(gps.satellites.value()); 24 | Serial.println("Latitude:"); 25 | Serial.println(gps.location.lat(), 6); 26 | Serial.println("Longitude:"); 27 | Serial.println(gps.location.lng(), 6); 28 | Serial.println("Speed MPH:"); 29 | Serial.println(gps.speed.mph()); 30 | Serial.println("Altitude Feet:"); 31 | Serial.println(gps.altitude.feet()); 32 | Serial.println(""); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Chapter#7 Enabling different Things to talk to each other/Indoor_Device_MKR_Wi-Fi_1010_sep07a.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Arduino-IoT-Cloud-for-Developers/7573bbb2039ca406b20e6718489c16b6e6792dff/Chapter#7 Enabling different Things to talk to each other/Indoor_Device_MKR_Wi-Fi_1010_sep07a.zip -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Arduino-IoT-Cloud-for-Developers/7573bbb2039ca406b20e6718489c16b6e6792dff/Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/.DS_Store -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/dashboard/create-dashboard.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=create-dashboard.js 4 | * Description: Below code will create the dashboard via API 5 | */ 6 | 7 | var AIotApi = require('@arduino/arduino-iot-client'); 8 | var rp = require('request-promise'); 9 | var util = require("util"); 10 | async function getToken() { 11 | var options = { 12 | method: 'POST', 13 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 14 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 15 | json: true, 16 | form: { 17 | grant_type: 'client_credentials', 18 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 19 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 20 | audience: 'https://api2.arduino.cc/iot' 21 | } 22 | }; 23 | 24 | try { 25 | const response = await rp(options); 26 | return response['access_token']; 27 | } 28 | catch (error) { 29 | console.error("Failed getting an access token: " + error) 30 | } 31 | } 32 | 33 | async function CreateDashboard(){ 34 | // Configure OAuth2 access token for authorization: oauth2 35 | var client = AIotApi.ApiClient.instance; 36 | var oauth2 = client.authentications['oauth2']; 37 | oauth2.accessToken = await getToken(); 38 | 39 | var api = new AIotApi.DashboardsV2Api(); 40 | var dashboardprop = { 41 | 'name':'Dashboard Created via API' 42 | }; 43 | var opts = { }; 44 | api.dashboardsV2Create(dashboardprop,opts).then(function(data) { 45 | console.log('Dashboard Created successfully. Returned data: ' + util.inspect(data)); 46 | }, function(error) { 47 | console.error(error); 48 | }); 49 | 50 | } 51 | 52 | CreateDashboard(); -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/dashboard/delete-dashboard.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=delete-dashboard.js 4 | * Description: Below code will delete dashboard via API on the bases of Dashboard ID 5 | */ 6 | 7 | var AIotApi = require('@arduino/arduino-iot-client'); 8 | var rp = require('request-promise'); 9 | async function getToken() { 10 | var options = { 11 | method: 'POST', 12 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 13 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 14 | json: true, 15 | form: { 16 | grant_type: 'client_credentials', 17 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 18 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 19 | audience: 'https://api2.arduino.cc/iot' 20 | } 21 | }; 22 | 23 | try { 24 | const response = await rp(options); 25 | return response['access_token']; 26 | } 27 | catch (error) { 28 | console.error("Failed getting an access token: " + error) 29 | } 30 | } 31 | 32 | 33 | 34 | async function DeleteDashboard(){ 35 | 36 | // Configure OAuth2 access token for authorization: oauth2 37 | var client = AIotApi.ApiClient.instance; 38 | var oauth2 = client.authentications['oauth2']; 39 | oauth2.accessToken = await getToken(); 40 | 41 | var api = new AIotApi.DashboardsV2Api() 42 | var dashboard_id="5b872702-059c-4895-a677-808981f31588"; 43 | var opts = { 44 | }; 45 | api.dashboardsV2Delete(dashboard_id, opts).then(function(data) { 46 | console.log('Dashboard Deleted successfully.'); 47 | }, function(error) { 48 | console.error(error); 49 | }); 50 | } 51 | 52 | DeleteDashboard(); -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/dashboard/list-dashboard.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=list-dashboard.js 4 | * Description: Below code will display all dashboards via API 5 | */ 6 | 7 | var AIotApi = require('@arduino/arduino-iot-client'); 8 | var rp = require('request-promise'); 9 | var util = require("util"); 10 | async function getToken() { 11 | var options = { 12 | method: 'POST', 13 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 14 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 15 | json: true, 16 | form: { 17 | grant_type: 'client_credentials', 18 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 19 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 20 | audience: 'https://api2.arduino.cc/iot' 21 | } 22 | }; 23 | 24 | try { 25 | const response = await rp(options); 26 | return response['access_token']; 27 | } 28 | catch (error) { 29 | console.error("Failed getting an access token: " + error) 30 | } 31 | } 32 | 33 | 34 | 35 | async function ListDashboard(){ 36 | 37 | // Configure OAuth2 access token for authorization: oauth2 38 | var client = AIotApi.ApiClient.instance; 39 | var oauth2 = client.authentications['oauth2']; 40 | oauth2.accessToken = await getToken(); 41 | 42 | var api = new AIotApi.DashboardsV2Api() 43 | var opts = { }; 44 | api.dashboardsV2List().then(function(data) { 45 | console.log(util.inspect(data)); 46 | }, function(error) { 47 | console.error(error); 48 | }); 49 | } 50 | 51 | ListDashboard(); -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/dashboard/show-dashboard.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=show-dashboard.js 4 | * Description: Below code will display the properties of specific dashboard via API on the bases of Dashboard ID 5 | */ 6 | 7 | var AIotApi = require('@arduino/arduino-iot-client'); 8 | var rp = require('request-promise'); 9 | var util = require("util"); 10 | async function getToken() { 11 | var options = { 12 | method: 'POST', 13 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 14 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 15 | json: true, 16 | form: { 17 | grant_type: 'client_credentials', 18 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 19 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 20 | audience: 'https://api2.arduino.cc/iot' 21 | } 22 | }; 23 | 24 | try { 25 | const response = await rp(options); 26 | return response['access_token']; 27 | } 28 | catch (error) { 29 | console.error("Failed getting an access token: " + error) 30 | } 31 | } 32 | 33 | 34 | 35 | async function ShowDashboard(){ 36 | 37 | // Configure OAuth2 access token for authorization: oauth2 38 | var client = AIotApi.ApiClient.instance; 39 | var oauth2 = client.authentications['oauth2']; 40 | oauth2.accessToken = await getToken(); 41 | 42 | var api = new AIotApi.DashboardsV2Api() 43 | var dashboard_id="f00aaaab-7faa-4ba6-bdd7-814377f296ba"; 44 | var opts = { 45 | }; 46 | api.dashboardsV2Show(dashboard_id, opts).then(function(data) { 47 | console.log(util.inspect(data)); 48 | }, function(error) { 49 | console.error(error); 50 | }); 51 | } 52 | 53 | ShowDashboard(); -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/dashboard/update-dashboard.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=update-dashboard.js 4 | * Description: Below code will update the properties of specific dashboard via API on the bases of Dashboard ID 5 | */ 6 | 7 | var AIotApi = require('@arduino/arduino-iot-client'); 8 | var rp = require('request-promise'); 9 | var util = require("util"); 10 | async function getToken() { 11 | var options = { 12 | method: 'POST', 13 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 14 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 15 | json: true, 16 | form: { 17 | grant_type: 'client_credentials', 18 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 19 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 20 | audience: 'https://api2.arduino.cc/iot' 21 | } 22 | }; 23 | 24 | try { 25 | const response = await rp(options); 26 | return response['access_token']; 27 | } 28 | catch (error) { 29 | console.error("Failed getting an access token: " + error) 30 | } 31 | } 32 | 33 | 34 | 35 | async function UpdateDashboard(){ 36 | 37 | // Configure OAuth2 access token for authorization: oauth2 38 | var client = AIotApi.ApiClient.instance; 39 | var oauth2 = client.authentications['oauth2']; 40 | oauth2.accessToken = await getToken(); 41 | 42 | var api = new AIotApi.DashboardsV2Api() 43 | var dashboard_id="5b872702-059c-4895-a677-808981f31588"; 44 | var dashboardprop = { 45 | 'name':'Dashboard Created via API Update' 46 | }; 47 | var opts = { 48 | }; 49 | api.dashboardsV2Update(dashboard_id,dashboardprop, opts).then(function(data) { 50 | console.log('Dashboard Updated successfully.'+ util.inspect(data)); 51 | }, function(error) { 52 | console.error(error); 53 | }); 54 | } 55 | 56 | UpdateDashboard(); -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/device/create-device.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=create-device.js 4 | * Description: Below code will create a new device via API 5 | */ 6 | 7 | var AIotApi = require('@arduino/arduino-iot-client'); 8 | var rp = require('request-promise'); 9 | var util = require("util"); 10 | async function getToken() { 11 | var options = { 12 | method: 'POST', 13 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 14 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 15 | json: true, 16 | form: { 17 | grant_type: 'client_credentials', 18 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 19 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 20 | audience: 'https://api2.arduino.cc/iot' 21 | } 22 | }; 23 | 24 | try { 25 | const response = await rp(options); 26 | return response['access_token']; 27 | } 28 | catch (error) { 29 | console.error("Failed getting an access token: " + error) 30 | } 31 | } 32 | 33 | 34 | 35 | async function CreateDevice(){ 36 | 37 | // Configure OAuth2 access token for authorization: oauth2 38 | var client = AIotApi.ApiClient.instance; 39 | var oauth2 = client.authentications['oauth2']; 40 | oauth2.accessToken = await getToken(); 41 | 42 | var api = new AIotApi.DevicesV2Api() 43 | 44 | 45 | var DeviceProperties = { 46 | 'name':'Sense Home XIAO Series', 47 | 'connection_type':'wifi', 48 | 'fqbn':'esp32:esp32:XIAO_ESP32C3', 49 | 'type':'login_and_secretkey_wifi' 50 | 51 | }; 52 | var options = { 53 | }; 54 | api.devicesV2Create(DeviceProperties, options).then(function(data) { 55 | console.log('Device Created successfully. Returned data: ' + util.inspect(data)); 56 | }, function(error) { 57 | console.error(error); 58 | }); 59 | } 60 | 61 | CreateDevice(); -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/device/delete-device.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=delete-device.js 4 | * Description: Below code will delete a device via API 5 | */ 6 | 7 | var AIotApi = require('@arduino/arduino-iot-client'); 8 | var rp = require('request-promise'); 9 | async function getToken() { 10 | var options = { 11 | method: 'POST', 12 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 13 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 14 | json: true, 15 | form: { 16 | grant_type: 'client_credentials', 17 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 18 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 19 | audience: 'https://api2.arduino.cc/iot' 20 | } 21 | }; 22 | 23 | try { 24 | const response = await rp(options); 25 | return response['access_token']; 26 | } 27 | catch (error) { 28 | console.error("Failed getting an access token: " + error) 29 | } 30 | } 31 | 32 | 33 | 34 | async function DeleteDevice(){ 35 | 36 | // Configure OAuth2 access token for authorization: oauth2 37 | var client = AIotApi.ApiClient.instance; 38 | var oauth2 = client.authentications['oauth2']; 39 | oauth2.accessToken = await getToken(); 40 | 41 | var api = new AIotApi.DevicesV2Api(); 42 | var DeviceID="84065d08-5cc1-4fbb-a950-7d29e6cd9ef0"; 43 | var options = { 44 | }; 45 | api.devicesV2Delete(DeviceID, options).then(function(data) { 46 | console.log('Device Deleted successfully. Returned data: ' + data); 47 | }, function(error) { 48 | console.error(error); 49 | }); 50 | } 51 | 52 | DeleteDevice(); -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/device/list-device.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=list-device.js 4 | * Description: Below code will show the list of all device via API 5 | */ 6 | 7 | var AIotApi = require('@arduino/arduino-iot-client'); 8 | var rp = require('request-promise'); 9 | async function getToken() { 10 | var options = { 11 | method: 'POST', 12 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 13 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 14 | json: true, 15 | form: { 16 | grant_type: 'client_credentials', 17 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 18 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 19 | audience: 'https://api2.arduino.cc/iot' 20 | } 21 | }; 22 | 23 | try { 24 | const response = await rp(options); 25 | return response['access_token']; 26 | } 27 | catch (error) { 28 | console.error("Failed getting an access token: " + error) 29 | } 30 | } 31 | 32 | 33 | 34 | async function ListDevice(){ 35 | 36 | // Configure OAuth2 access token for authorization: oauth2 37 | var client = AIotApi.ApiClient.instance; 38 | var oauth2 = client.authentications['oauth2']; 39 | oauth2.accessToken = await getToken(); 40 | 41 | var api = new AIotApi.DevicesV2Api() 42 | var opts = { 43 | 'acrossUserIds': false // {Boolean} If true, returns all the devices 44 | }; 45 | api.devicesV2List(opts).then(function(data) { 46 | for(var i=0;i=6.0.0" 23 | } 24 | }, 25 | "node_modules/@arduino/arduino-iot-client": { 26 | "version": "1.4.2", 27 | "resolved": "https://registry.npmjs.org/@arduino/arduino-iot-client/-/arduino-iot-client-1.4.2.tgz", 28 | "integrity": "sha512-mlIBype4l+kSnGnNH8hO3CjmoDHRJpLCpjiySiKmNL0z87Wcz+1b5LLiTT/748UmbB/2FrgPZsDn8RVbB+FAhw==", 29 | "dependencies": { 30 | "@babel/cli": "^7.0.0", 31 | "superagent": "3.7.0" 32 | } 33 | }, 34 | "node_modules/@babel/cli": { 35 | "version": "7.21.0", 36 | "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.21.0.tgz", 37 | "integrity": "sha512-xi7CxyS8XjSyiwUGCfwf+brtJxjW1/ZTcBUkP10xawIEXLX5HzLn+3aXkgxozcP2UhRhtKTmQurw9Uaes7jZrA==", 38 | "dependencies": { 39 | "@jridgewell/trace-mapping": "^0.3.17", 40 | "commander": "^4.0.1", 41 | "convert-source-map": "^1.1.0", 42 | "fs-readdir-recursive": "^1.1.0", 43 | "glob": "^7.2.0", 44 | "make-dir": "^2.1.0", 45 | "slash": "^2.0.0" 46 | }, 47 | "bin": { 48 | "babel": "bin/babel.js", 49 | "babel-external-helpers": "bin/babel-external-helpers.js" 50 | }, 51 | "engines": { 52 | "node": ">=6.9.0" 53 | }, 54 | "optionalDependencies": { 55 | "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3", 56 | "chokidar": "^3.4.0" 57 | }, 58 | "peerDependencies": { 59 | "@babel/core": "^7.0.0-0" 60 | } 61 | }, 62 | "node_modules/@babel/code-frame": { 63 | "version": "7.21.4", 64 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", 65 | "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", 66 | "peer": true, 67 | "dependencies": { 68 | "@babel/highlight": "^7.18.6" 69 | }, 70 | "engines": { 71 | "node": ">=6.9.0" 72 | } 73 | }, 74 | "node_modules/@babel/compat-data": { 75 | "version": "7.21.4", 76 | "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", 77 | "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==", 78 | "peer": true, 79 | "engines": { 80 | "node": ">=6.9.0" 81 | } 82 | }, 83 | "node_modules/@babel/core": { 84 | "version": "7.21.4", 85 | "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", 86 | "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", 87 | "peer": true, 88 | "dependencies": { 89 | "@ampproject/remapping": "^2.2.0", 90 | "@babel/code-frame": "^7.21.4", 91 | "@babel/generator": "^7.21.4", 92 | "@babel/helper-compilation-targets": "^7.21.4", 93 | "@babel/helper-module-transforms": "^7.21.2", 94 | "@babel/helpers": "^7.21.0", 95 | "@babel/parser": "^7.21.4", 96 | "@babel/template": "^7.20.7", 97 | "@babel/traverse": "^7.21.4", 98 | "@babel/types": "^7.21.4", 99 | "convert-source-map": "^1.7.0", 100 | "debug": "^4.1.0", 101 | "gensync": "^1.0.0-beta.2", 102 | "json5": "^2.2.2", 103 | "semver": "^6.3.0" 104 | }, 105 | "engines": { 106 | "node": ">=6.9.0" 107 | }, 108 | "funding": { 109 | "type": "opencollective", 110 | "url": "https://opencollective.com/babel" 111 | } 112 | }, 113 | "node_modules/@babel/generator": { 114 | "version": "7.21.4", 115 | "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", 116 | "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", 117 | "peer": true, 118 | "dependencies": { 119 | "@babel/types": "^7.21.4", 120 | "@jridgewell/gen-mapping": "^0.3.2", 121 | "@jridgewell/trace-mapping": "^0.3.17", 122 | "jsesc": "^2.5.1" 123 | }, 124 | "engines": { 125 | "node": ">=6.9.0" 126 | } 127 | }, 128 | "node_modules/@babel/helper-compilation-targets": { 129 | "version": "7.21.4", 130 | "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", 131 | "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", 132 | "peer": true, 133 | "dependencies": { 134 | "@babel/compat-data": "^7.21.4", 135 | "@babel/helper-validator-option": "^7.21.0", 136 | "browserslist": "^4.21.3", 137 | "lru-cache": "^5.1.1", 138 | "semver": "^6.3.0" 139 | }, 140 | "engines": { 141 | "node": ">=6.9.0" 142 | }, 143 | "peerDependencies": { 144 | "@babel/core": "^7.0.0" 145 | } 146 | }, 147 | "node_modules/@babel/helper-environment-visitor": { 148 | "version": "7.18.9", 149 | "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", 150 | "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", 151 | "peer": true, 152 | "engines": { 153 | "node": ">=6.9.0" 154 | } 155 | }, 156 | "node_modules/@babel/helper-function-name": { 157 | "version": "7.21.0", 158 | "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", 159 | "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", 160 | "peer": true, 161 | "dependencies": { 162 | "@babel/template": "^7.20.7", 163 | "@babel/types": "^7.21.0" 164 | }, 165 | "engines": { 166 | "node": ">=6.9.0" 167 | } 168 | }, 169 | "node_modules/@babel/helper-hoist-variables": { 170 | "version": "7.18.6", 171 | "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", 172 | "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", 173 | "peer": true, 174 | "dependencies": { 175 | "@babel/types": "^7.18.6" 176 | }, 177 | "engines": { 178 | "node": ">=6.9.0" 179 | } 180 | }, 181 | "node_modules/@babel/helper-module-imports": { 182 | "version": "7.21.4", 183 | "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", 184 | "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", 185 | "peer": true, 186 | "dependencies": { 187 | "@babel/types": "^7.21.4" 188 | }, 189 | "engines": { 190 | "node": ">=6.9.0" 191 | } 192 | }, 193 | "node_modules/@babel/helper-module-transforms": { 194 | "version": "7.21.2", 195 | "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", 196 | "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", 197 | "peer": true, 198 | "dependencies": { 199 | "@babel/helper-environment-visitor": "^7.18.9", 200 | "@babel/helper-module-imports": "^7.18.6", 201 | "@babel/helper-simple-access": "^7.20.2", 202 | "@babel/helper-split-export-declaration": "^7.18.6", 203 | "@babel/helper-validator-identifier": "^7.19.1", 204 | "@babel/template": "^7.20.7", 205 | "@babel/traverse": "^7.21.2", 206 | "@babel/types": "^7.21.2" 207 | }, 208 | "engines": { 209 | "node": ">=6.9.0" 210 | } 211 | }, 212 | "node_modules/@babel/helper-simple-access": { 213 | "version": "7.20.2", 214 | "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", 215 | "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", 216 | "peer": true, 217 | "dependencies": { 218 | "@babel/types": "^7.20.2" 219 | }, 220 | "engines": { 221 | "node": ">=6.9.0" 222 | } 223 | }, 224 | "node_modules/@babel/helper-split-export-declaration": { 225 | "version": "7.18.6", 226 | "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", 227 | "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", 228 | "peer": true, 229 | "dependencies": { 230 | "@babel/types": "^7.18.6" 231 | }, 232 | "engines": { 233 | "node": ">=6.9.0" 234 | } 235 | }, 236 | "node_modules/@babel/helper-string-parser": { 237 | "version": "7.19.4", 238 | "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", 239 | "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", 240 | "peer": true, 241 | "engines": { 242 | "node": ">=6.9.0" 243 | } 244 | }, 245 | "node_modules/@babel/helper-validator-identifier": { 246 | "version": "7.19.1", 247 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", 248 | "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", 249 | "peer": true, 250 | "engines": { 251 | "node": ">=6.9.0" 252 | } 253 | }, 254 | "node_modules/@babel/helper-validator-option": { 255 | "version": "7.21.0", 256 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", 257 | "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", 258 | "peer": true, 259 | "engines": { 260 | "node": ">=6.9.0" 261 | } 262 | }, 263 | "node_modules/@babel/helpers": { 264 | "version": "7.21.0", 265 | "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", 266 | "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", 267 | "peer": true, 268 | "dependencies": { 269 | "@babel/template": "^7.20.7", 270 | "@babel/traverse": "^7.21.0", 271 | "@babel/types": "^7.21.0" 272 | }, 273 | "engines": { 274 | "node": ">=6.9.0" 275 | } 276 | }, 277 | "node_modules/@babel/highlight": { 278 | "version": "7.18.6", 279 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", 280 | "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", 281 | "peer": true, 282 | "dependencies": { 283 | "@babel/helper-validator-identifier": "^7.18.6", 284 | "chalk": "^2.0.0", 285 | "js-tokens": "^4.0.0" 286 | }, 287 | "engines": { 288 | "node": ">=6.9.0" 289 | } 290 | }, 291 | "node_modules/@babel/parser": { 292 | "version": "7.21.4", 293 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", 294 | "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", 295 | "peer": true, 296 | "bin": { 297 | "parser": "bin/babel-parser.js" 298 | }, 299 | "engines": { 300 | "node": ">=6.0.0" 301 | } 302 | }, 303 | "node_modules/@babel/template": { 304 | "version": "7.20.7", 305 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", 306 | "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", 307 | "peer": true, 308 | "dependencies": { 309 | "@babel/code-frame": "^7.18.6", 310 | "@babel/parser": "^7.20.7", 311 | "@babel/types": "^7.20.7" 312 | }, 313 | "engines": { 314 | "node": ">=6.9.0" 315 | } 316 | }, 317 | "node_modules/@babel/traverse": { 318 | "version": "7.21.4", 319 | "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", 320 | "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", 321 | "peer": true, 322 | "dependencies": { 323 | "@babel/code-frame": "^7.21.4", 324 | "@babel/generator": "^7.21.4", 325 | "@babel/helper-environment-visitor": "^7.18.9", 326 | "@babel/helper-function-name": "^7.21.0", 327 | "@babel/helper-hoist-variables": "^7.18.6", 328 | "@babel/helper-split-export-declaration": "^7.18.6", 329 | "@babel/parser": "^7.21.4", 330 | "@babel/types": "^7.21.4", 331 | "debug": "^4.1.0", 332 | "globals": "^11.1.0" 333 | }, 334 | "engines": { 335 | "node": ">=6.9.0" 336 | } 337 | }, 338 | "node_modules/@babel/types": { 339 | "version": "7.21.4", 340 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", 341 | "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", 342 | "peer": true, 343 | "dependencies": { 344 | "@babel/helper-string-parser": "^7.19.4", 345 | "@babel/helper-validator-identifier": "^7.19.1", 346 | "to-fast-properties": "^2.0.0" 347 | }, 348 | "engines": { 349 | "node": ">=6.9.0" 350 | } 351 | }, 352 | "node_modules/@jridgewell/gen-mapping": { 353 | "version": "0.3.3", 354 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", 355 | "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", 356 | "peer": true, 357 | "dependencies": { 358 | "@jridgewell/set-array": "^1.0.1", 359 | "@jridgewell/sourcemap-codec": "^1.4.10", 360 | "@jridgewell/trace-mapping": "^0.3.9" 361 | }, 362 | "engines": { 363 | "node": ">=6.0.0" 364 | } 365 | }, 366 | "node_modules/@jridgewell/resolve-uri": { 367 | "version": "3.1.0", 368 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", 369 | "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", 370 | "engines": { 371 | "node": ">=6.0.0" 372 | } 373 | }, 374 | "node_modules/@jridgewell/set-array": { 375 | "version": "1.1.2", 376 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", 377 | "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", 378 | "peer": true, 379 | "engines": { 380 | "node": ">=6.0.0" 381 | } 382 | }, 383 | "node_modules/@jridgewell/sourcemap-codec": { 384 | "version": "1.4.15", 385 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", 386 | "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", 387 | "peer": true 388 | }, 389 | "node_modules/@jridgewell/trace-mapping": { 390 | "version": "0.3.18", 391 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", 392 | "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", 393 | "dependencies": { 394 | "@jridgewell/resolve-uri": "3.1.0", 395 | "@jridgewell/sourcemap-codec": "1.4.14" 396 | } 397 | }, 398 | "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { 399 | "version": "1.4.14", 400 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", 401 | "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" 402 | }, 403 | "node_modules/@nicolo-ribaudo/chokidar-2": { 404 | "version": "2.1.8-no-fsevents.3", 405 | "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", 406 | "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==", 407 | "optional": true 408 | }, 409 | "node_modules/ajv": { 410 | "version": "6.12.6", 411 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 412 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 413 | "peer": true, 414 | "dependencies": { 415 | "fast-deep-equal": "^3.1.1", 416 | "fast-json-stable-stringify": "^2.0.0", 417 | "json-schema-traverse": "^0.4.1", 418 | "uri-js": "^4.2.2" 419 | }, 420 | "funding": { 421 | "type": "github", 422 | "url": "https://github.com/sponsors/epoberezkin" 423 | } 424 | }, 425 | "node_modules/ansi-styles": { 426 | "version": "3.2.1", 427 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 428 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 429 | "peer": true, 430 | "dependencies": { 431 | "color-convert": "^1.9.0" 432 | }, 433 | "engines": { 434 | "node": ">=4" 435 | } 436 | }, 437 | "node_modules/anymatch": { 438 | "version": "3.1.3", 439 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 440 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 441 | "optional": true, 442 | "dependencies": { 443 | "normalize-path": "^3.0.0", 444 | "picomatch": "^2.0.4" 445 | }, 446 | "engines": { 447 | "node": ">= 8" 448 | } 449 | }, 450 | "node_modules/asn1": { 451 | "version": "0.2.6", 452 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", 453 | "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", 454 | "peer": true, 455 | "dependencies": { 456 | "safer-buffer": "~2.1.0" 457 | } 458 | }, 459 | "node_modules/assert-plus": { 460 | "version": "1.0.0", 461 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 462 | "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", 463 | "peer": true, 464 | "engines": { 465 | "node": ">=0.8" 466 | } 467 | }, 468 | "node_modules/asynckit": { 469 | "version": "0.4.0", 470 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 471 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" 472 | }, 473 | "node_modules/aws-sign2": { 474 | "version": "0.7.0", 475 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 476 | "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", 477 | "peer": true, 478 | "engines": { 479 | "node": "*" 480 | } 481 | }, 482 | "node_modules/aws4": { 483 | "version": "1.12.0", 484 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", 485 | "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", 486 | "peer": true 487 | }, 488 | "node_modules/balanced-match": { 489 | "version": "1.0.2", 490 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 491 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 492 | }, 493 | "node_modules/bcrypt-pbkdf": { 494 | "version": "1.0.2", 495 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 496 | "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", 497 | "peer": true, 498 | "dependencies": { 499 | "tweetnacl": "^0.14.3" 500 | } 501 | }, 502 | "node_modules/binary-extensions": { 503 | "version": "2.2.0", 504 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 505 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 506 | "optional": true, 507 | "engines": { 508 | "node": ">=8" 509 | } 510 | }, 511 | "node_modules/bluebird": { 512 | "version": "3.7.2", 513 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 514 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" 515 | }, 516 | "node_modules/brace-expansion": { 517 | "version": "1.1.11", 518 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 519 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 520 | "dependencies": { 521 | "balanced-match": "^1.0.0", 522 | "concat-map": "0.0.1" 523 | } 524 | }, 525 | "node_modules/braces": { 526 | "version": "3.0.2", 527 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 528 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 529 | "optional": true, 530 | "dependencies": { 531 | "fill-range": "^7.0.1" 532 | }, 533 | "engines": { 534 | "node": ">=8" 535 | } 536 | }, 537 | "node_modules/browserslist": { 538 | "version": "4.21.5", 539 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", 540 | "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", 541 | "funding": [ 542 | { 543 | "type": "opencollective", 544 | "url": "https://opencollective.com/browserslist" 545 | }, 546 | { 547 | "type": "tidelift", 548 | "url": "https://tidelift.com/funding/github/npm/browserslist" 549 | } 550 | ], 551 | "peer": true, 552 | "dependencies": { 553 | "caniuse-lite": "^1.0.30001449", 554 | "electron-to-chromium": "^1.4.284", 555 | "node-releases": "^2.0.8", 556 | "update-browserslist-db": "^1.0.10" 557 | }, 558 | "bin": { 559 | "browserslist": "cli.js" 560 | }, 561 | "engines": { 562 | "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" 563 | } 564 | }, 565 | "node_modules/call-bind": { 566 | "version": "1.0.2", 567 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 568 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 569 | "dependencies": { 570 | "function-bind": "^1.1.1", 571 | "get-intrinsic": "^1.0.2" 572 | }, 573 | "funding": { 574 | "url": "https://github.com/sponsors/ljharb" 575 | } 576 | }, 577 | "node_modules/caniuse-lite": { 578 | "version": "1.0.30001477", 579 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001477.tgz", 580 | "integrity": "sha512-lZim4iUHhGcy5p+Ri/G7m84hJwncj+Kz7S5aD4hoQfslKZJgt0tHc/hafVbqHC5bbhHb+mrW2JOUHkI5KH7toQ==", 581 | "funding": [ 582 | { 583 | "type": "opencollective", 584 | "url": "https://opencollective.com/browserslist" 585 | }, 586 | { 587 | "type": "tidelift", 588 | "url": "https://tidelift.com/funding/github/npm/caniuse-lite" 589 | }, 590 | { 591 | "type": "github", 592 | "url": "https://github.com/sponsors/ai" 593 | } 594 | ], 595 | "peer": true 596 | }, 597 | "node_modules/caseless": { 598 | "version": "0.12.0", 599 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 600 | "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", 601 | "peer": true 602 | }, 603 | "node_modules/chalk": { 604 | "version": "2.4.2", 605 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 606 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 607 | "peer": true, 608 | "dependencies": { 609 | "ansi-styles": "^3.2.1", 610 | "escape-string-regexp": "^1.0.5", 611 | "supports-color": "^5.3.0" 612 | }, 613 | "engines": { 614 | "node": ">=4" 615 | } 616 | }, 617 | "node_modules/chokidar": { 618 | "version": "3.5.3", 619 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 620 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 621 | "funding": [ 622 | { 623 | "type": "individual", 624 | "url": "https://paulmillr.com/funding/" 625 | } 626 | ], 627 | "optional": true, 628 | "dependencies": { 629 | "anymatch": "~3.1.2", 630 | "braces": "~3.0.2", 631 | "glob-parent": "~5.1.2", 632 | "is-binary-path": "~2.1.0", 633 | "is-glob": "~4.0.1", 634 | "normalize-path": "~3.0.0", 635 | "readdirp": "~3.6.0" 636 | }, 637 | "engines": { 638 | "node": ">= 8.10.0" 639 | }, 640 | "optionalDependencies": { 641 | "fsevents": "~2.3.2" 642 | } 643 | }, 644 | "node_modules/color-convert": { 645 | "version": "1.9.3", 646 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 647 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 648 | "peer": true, 649 | "dependencies": { 650 | "color-name": "1.1.3" 651 | } 652 | }, 653 | "node_modules/color-name": { 654 | "version": "1.1.3", 655 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 656 | "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", 657 | "peer": true 658 | }, 659 | "node_modules/combined-stream": { 660 | "version": "1.0.8", 661 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 662 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 663 | "dependencies": { 664 | "delayed-stream": "~1.0.0" 665 | }, 666 | "engines": { 667 | "node": ">= 0.8" 668 | } 669 | }, 670 | "node_modules/commander": { 671 | "version": "4.1.1", 672 | "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", 673 | "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", 674 | "engines": { 675 | "node": ">= 6" 676 | } 677 | }, 678 | "node_modules/component-emitter": { 679 | "version": "1.3.0", 680 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", 681 | "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" 682 | }, 683 | "node_modules/concat-map": { 684 | "version": "0.0.1", 685 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 686 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 687 | }, 688 | "node_modules/convert-source-map": { 689 | "version": "1.9.0", 690 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", 691 | "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" 692 | }, 693 | "node_modules/cookiejar": { 694 | "version": "2.1.4", 695 | "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", 696 | "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==" 697 | }, 698 | "node_modules/core-util-is": { 699 | "version": "1.0.3", 700 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", 701 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" 702 | }, 703 | "node_modules/dashdash": { 704 | "version": "1.14.1", 705 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 706 | "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", 707 | "peer": true, 708 | "dependencies": { 709 | "assert-plus": "^1.0.0" 710 | }, 711 | "engines": { 712 | "node": ">=0.10" 713 | } 714 | }, 715 | "node_modules/debug": { 716 | "version": "4.3.4", 717 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 718 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 719 | "peer": true, 720 | "dependencies": { 721 | "ms": "2.1.2" 722 | }, 723 | "engines": { 724 | "node": ">=6.0" 725 | }, 726 | "peerDependenciesMeta": { 727 | "supports-color": { 728 | "optional": true 729 | } 730 | } 731 | }, 732 | "node_modules/delayed-stream": { 733 | "version": "1.0.0", 734 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 735 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 736 | "engines": { 737 | "node": ">=0.4.0" 738 | } 739 | }, 740 | "node_modules/ecc-jsbn": { 741 | "version": "0.1.2", 742 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 743 | "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", 744 | "peer": true, 745 | "dependencies": { 746 | "jsbn": "~0.1.0", 747 | "safer-buffer": "^2.1.0" 748 | } 749 | }, 750 | "node_modules/electron-to-chromium": { 751 | "version": "1.4.356", 752 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.356.tgz", 753 | "integrity": "sha512-nEftV1dRX3omlxAj42FwqRZT0i4xd2dIg39sog/CnCJeCcL1TRd2Uh0i9Oebgv8Ou0vzTPw++xc+Z20jzS2B6A==", 754 | "peer": true 755 | }, 756 | "node_modules/escalade": { 757 | "version": "3.1.1", 758 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 759 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 760 | "peer": true, 761 | "engines": { 762 | "node": ">=6" 763 | } 764 | }, 765 | "node_modules/escape-string-regexp": { 766 | "version": "1.0.5", 767 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 768 | "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", 769 | "peer": true, 770 | "engines": { 771 | "node": ">=0.8.0" 772 | } 773 | }, 774 | "node_modules/extend": { 775 | "version": "3.0.2", 776 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 777 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 778 | }, 779 | "node_modules/extsprintf": { 780 | "version": "1.3.0", 781 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 782 | "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", 783 | "engines": [ 784 | "node >=0.6.0" 785 | ], 786 | "peer": true 787 | }, 788 | "node_modules/fast-deep-equal": { 789 | "version": "3.1.3", 790 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 791 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 792 | "peer": true 793 | }, 794 | "node_modules/fast-json-stable-stringify": { 795 | "version": "2.1.0", 796 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 797 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 798 | "peer": true 799 | }, 800 | "node_modules/fill-range": { 801 | "version": "7.0.1", 802 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 803 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 804 | "optional": true, 805 | "dependencies": { 806 | "to-regex-range": "^5.0.1" 807 | }, 808 | "engines": { 809 | "node": ">=8" 810 | } 811 | }, 812 | "node_modules/forever-agent": { 813 | "version": "0.6.1", 814 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 815 | "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", 816 | "peer": true, 817 | "engines": { 818 | "node": "*" 819 | } 820 | }, 821 | "node_modules/form-data": { 822 | "version": "2.5.1", 823 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", 824 | "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", 825 | "dependencies": { 826 | "asynckit": "^0.4.0", 827 | "combined-stream": "^1.0.6", 828 | "mime-types": "^2.1.12" 829 | }, 830 | "engines": { 831 | "node": ">= 0.12" 832 | } 833 | }, 834 | "node_modules/formidable": { 835 | "version": "1.2.6", 836 | "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", 837 | "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", 838 | "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", 839 | "funding": { 840 | "url": "https://ko-fi.com/tunnckoCore/commissions" 841 | } 842 | }, 843 | "node_modules/fs-readdir-recursive": { 844 | "version": "1.1.0", 845 | "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", 846 | "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==" 847 | }, 848 | "node_modules/fs.realpath": { 849 | "version": "1.0.0", 850 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 851 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" 852 | }, 853 | "node_modules/fsevents": { 854 | "version": "2.3.2", 855 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 856 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 857 | "hasInstallScript": true, 858 | "optional": true, 859 | "os": [ 860 | "darwin" 861 | ], 862 | "engines": { 863 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 864 | } 865 | }, 866 | "node_modules/function-bind": { 867 | "version": "1.1.1", 868 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 869 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 870 | }, 871 | "node_modules/gensync": { 872 | "version": "1.0.0-beta.2", 873 | "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", 874 | "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", 875 | "peer": true, 876 | "engines": { 877 | "node": ">=6.9.0" 878 | } 879 | }, 880 | "node_modules/get-intrinsic": { 881 | "version": "1.2.0", 882 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", 883 | "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", 884 | "dependencies": { 885 | "function-bind": "^1.1.1", 886 | "has": "^1.0.3", 887 | "has-symbols": "^1.0.3" 888 | }, 889 | "funding": { 890 | "url": "https://github.com/sponsors/ljharb" 891 | } 892 | }, 893 | "node_modules/getpass": { 894 | "version": "0.1.7", 895 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 896 | "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", 897 | "peer": true, 898 | "dependencies": { 899 | "assert-plus": "^1.0.0" 900 | } 901 | }, 902 | "node_modules/glob": { 903 | "version": "7.2.3", 904 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", 905 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 906 | "dependencies": { 907 | "fs.realpath": "^1.0.0", 908 | "inflight": "^1.0.4", 909 | "inherits": "2", 910 | "minimatch": "^3.1.1", 911 | "once": "^1.3.0", 912 | "path-is-absolute": "^1.0.0" 913 | }, 914 | "engines": { 915 | "node": "*" 916 | }, 917 | "funding": { 918 | "url": "https://github.com/sponsors/isaacs" 919 | } 920 | }, 921 | "node_modules/glob-parent": { 922 | "version": "5.1.2", 923 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 924 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 925 | "optional": true, 926 | "dependencies": { 927 | "is-glob": "^4.0.1" 928 | }, 929 | "engines": { 930 | "node": ">= 6" 931 | } 932 | }, 933 | "node_modules/globals": { 934 | "version": "11.12.0", 935 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 936 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", 937 | "peer": true, 938 | "engines": { 939 | "node": ">=4" 940 | } 941 | }, 942 | "node_modules/har-schema": { 943 | "version": "2.0.0", 944 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 945 | "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", 946 | "peer": true, 947 | "engines": { 948 | "node": ">=4" 949 | } 950 | }, 951 | "node_modules/har-validator": { 952 | "version": "5.1.5", 953 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", 954 | "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", 955 | "deprecated": "this library is no longer supported", 956 | "peer": true, 957 | "dependencies": { 958 | "ajv": "^6.12.3", 959 | "har-schema": "^2.0.0" 960 | }, 961 | "engines": { 962 | "node": ">=6" 963 | } 964 | }, 965 | "node_modules/has": { 966 | "version": "1.0.3", 967 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 968 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 969 | "dependencies": { 970 | "function-bind": "^1.1.1" 971 | }, 972 | "engines": { 973 | "node": ">= 0.4.0" 974 | } 975 | }, 976 | "node_modules/has-flag": { 977 | "version": "3.0.0", 978 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 979 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 980 | "peer": true, 981 | "engines": { 982 | "node": ">=4" 983 | } 984 | }, 985 | "node_modules/has-symbols": { 986 | "version": "1.0.3", 987 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 988 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 989 | "engines": { 990 | "node": ">= 0.4" 991 | }, 992 | "funding": { 993 | "url": "https://github.com/sponsors/ljharb" 994 | } 995 | }, 996 | "node_modules/http-signature": { 997 | "version": "1.2.0", 998 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 999 | "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", 1000 | "peer": true, 1001 | "dependencies": { 1002 | "assert-plus": "^1.0.0", 1003 | "jsprim": "^1.2.2", 1004 | "sshpk": "^1.7.0" 1005 | }, 1006 | "engines": { 1007 | "node": ">=0.8", 1008 | "npm": ">=1.3.7" 1009 | } 1010 | }, 1011 | "node_modules/inflight": { 1012 | "version": "1.0.6", 1013 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1014 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 1015 | "dependencies": { 1016 | "once": "^1.3.0", 1017 | "wrappy": "1" 1018 | } 1019 | }, 1020 | "node_modules/inherits": { 1021 | "version": "2.0.4", 1022 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1023 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1024 | }, 1025 | "node_modules/is-binary-path": { 1026 | "version": "2.1.0", 1027 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 1028 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 1029 | "optional": true, 1030 | "dependencies": { 1031 | "binary-extensions": "^2.0.0" 1032 | }, 1033 | "engines": { 1034 | "node": ">=8" 1035 | } 1036 | }, 1037 | "node_modules/is-extglob": { 1038 | "version": "2.1.1", 1039 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1040 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 1041 | "optional": true, 1042 | "engines": { 1043 | "node": ">=0.10.0" 1044 | } 1045 | }, 1046 | "node_modules/is-glob": { 1047 | "version": "4.0.3", 1048 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1049 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1050 | "optional": true, 1051 | "dependencies": { 1052 | "is-extglob": "^2.1.1" 1053 | }, 1054 | "engines": { 1055 | "node": ">=0.10.0" 1056 | } 1057 | }, 1058 | "node_modules/is-number": { 1059 | "version": "7.0.0", 1060 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1061 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1062 | "optional": true, 1063 | "engines": { 1064 | "node": ">=0.12.0" 1065 | } 1066 | }, 1067 | "node_modules/is-typedarray": { 1068 | "version": "1.0.0", 1069 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 1070 | "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", 1071 | "peer": true 1072 | }, 1073 | "node_modules/isarray": { 1074 | "version": "1.0.0", 1075 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1076 | "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" 1077 | }, 1078 | "node_modules/isstream": { 1079 | "version": "0.1.2", 1080 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 1081 | "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", 1082 | "peer": true 1083 | }, 1084 | "node_modules/js-tokens": { 1085 | "version": "4.0.0", 1086 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 1087 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 1088 | "peer": true 1089 | }, 1090 | "node_modules/jsbn": { 1091 | "version": "0.1.1", 1092 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 1093 | "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", 1094 | "peer": true 1095 | }, 1096 | "node_modules/jsesc": { 1097 | "version": "2.5.2", 1098 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", 1099 | "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", 1100 | "peer": true, 1101 | "bin": { 1102 | "jsesc": "bin/jsesc" 1103 | }, 1104 | "engines": { 1105 | "node": ">=4" 1106 | } 1107 | }, 1108 | "node_modules/json-schema": { 1109 | "version": "0.4.0", 1110 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", 1111 | "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", 1112 | "peer": true 1113 | }, 1114 | "node_modules/json-schema-traverse": { 1115 | "version": "0.4.1", 1116 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1117 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1118 | "peer": true 1119 | }, 1120 | "node_modules/json-stringify-safe": { 1121 | "version": "5.0.1", 1122 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 1123 | "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", 1124 | "peer": true 1125 | }, 1126 | "node_modules/json5": { 1127 | "version": "2.2.3", 1128 | "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", 1129 | "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", 1130 | "peer": true, 1131 | "bin": { 1132 | "json5": "lib/cli.js" 1133 | }, 1134 | "engines": { 1135 | "node": ">=6" 1136 | } 1137 | }, 1138 | "node_modules/jsprim": { 1139 | "version": "1.4.2", 1140 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", 1141 | "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", 1142 | "peer": true, 1143 | "dependencies": { 1144 | "assert-plus": "1.0.0", 1145 | "extsprintf": "1.3.0", 1146 | "json-schema": "0.4.0", 1147 | "verror": "1.10.0" 1148 | }, 1149 | "engines": { 1150 | "node": ">=0.6.0" 1151 | } 1152 | }, 1153 | "node_modules/lodash": { 1154 | "version": "4.17.21", 1155 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 1156 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 1157 | }, 1158 | "node_modules/lru-cache": { 1159 | "version": "5.1.1", 1160 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", 1161 | "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", 1162 | "peer": true, 1163 | "dependencies": { 1164 | "yallist": "^3.0.2" 1165 | } 1166 | }, 1167 | "node_modules/make-dir": { 1168 | "version": "2.1.0", 1169 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", 1170 | "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", 1171 | "dependencies": { 1172 | "pify": "^4.0.1", 1173 | "semver": "^5.6.0" 1174 | }, 1175 | "engines": { 1176 | "node": ">=6" 1177 | } 1178 | }, 1179 | "node_modules/make-dir/node_modules/semver": { 1180 | "version": "5.7.1", 1181 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1182 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1183 | "bin": { 1184 | "semver": "bin/semver" 1185 | } 1186 | }, 1187 | "node_modules/methods": { 1188 | "version": "1.1.2", 1189 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1190 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 1191 | "engines": { 1192 | "node": ">= 0.6" 1193 | } 1194 | }, 1195 | "node_modules/mime": { 1196 | "version": "1.6.0", 1197 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1198 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 1199 | "bin": { 1200 | "mime": "cli.js" 1201 | }, 1202 | "engines": { 1203 | "node": ">=4" 1204 | } 1205 | }, 1206 | "node_modules/mime-db": { 1207 | "version": "1.52.0", 1208 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1209 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 1210 | "engines": { 1211 | "node": ">= 0.6" 1212 | } 1213 | }, 1214 | "node_modules/mime-types": { 1215 | "version": "2.1.35", 1216 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1217 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1218 | "dependencies": { 1219 | "mime-db": "1.52.0" 1220 | }, 1221 | "engines": { 1222 | "node": ">= 0.6" 1223 | } 1224 | }, 1225 | "node_modules/minimatch": { 1226 | "version": "3.1.2", 1227 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1228 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1229 | "dependencies": { 1230 | "brace-expansion": "^1.1.7" 1231 | }, 1232 | "engines": { 1233 | "node": "*" 1234 | } 1235 | }, 1236 | "node_modules/ms": { 1237 | "version": "2.1.2", 1238 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1239 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 1240 | }, 1241 | "node_modules/node-releases": { 1242 | "version": "2.0.10", 1243 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", 1244 | "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", 1245 | "peer": true 1246 | }, 1247 | "node_modules/normalize-path": { 1248 | "version": "3.0.0", 1249 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1250 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1251 | "optional": true, 1252 | "engines": { 1253 | "node": ">=0.10.0" 1254 | } 1255 | }, 1256 | "node_modules/oauth-sign": { 1257 | "version": "0.9.0", 1258 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 1259 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", 1260 | "peer": true, 1261 | "engines": { 1262 | "node": "*" 1263 | } 1264 | }, 1265 | "node_modules/object-inspect": { 1266 | "version": "1.12.3", 1267 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", 1268 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", 1269 | "funding": { 1270 | "url": "https://github.com/sponsors/ljharb" 1271 | } 1272 | }, 1273 | "node_modules/once": { 1274 | "version": "1.4.0", 1275 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1276 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1277 | "dependencies": { 1278 | "wrappy": "1" 1279 | } 1280 | }, 1281 | "node_modules/path-is-absolute": { 1282 | "version": "1.0.1", 1283 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1284 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 1285 | "engines": { 1286 | "node": ">=0.10.0" 1287 | } 1288 | }, 1289 | "node_modules/performance-now": { 1290 | "version": "2.1.0", 1291 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 1292 | "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", 1293 | "peer": true 1294 | }, 1295 | "node_modules/picocolors": { 1296 | "version": "1.0.0", 1297 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 1298 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 1299 | "peer": true 1300 | }, 1301 | "node_modules/picomatch": { 1302 | "version": "2.3.1", 1303 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1304 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1305 | "optional": true, 1306 | "engines": { 1307 | "node": ">=8.6" 1308 | }, 1309 | "funding": { 1310 | "url": "https://github.com/sponsors/jonschlinkert" 1311 | } 1312 | }, 1313 | "node_modules/pify": { 1314 | "version": "4.0.1", 1315 | "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", 1316 | "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", 1317 | "engines": { 1318 | "node": ">=6" 1319 | } 1320 | }, 1321 | "node_modules/process-nextick-args": { 1322 | "version": "2.0.1", 1323 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1324 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 1325 | }, 1326 | "node_modules/psl": { 1327 | "version": "1.9.0", 1328 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", 1329 | "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" 1330 | }, 1331 | "node_modules/punycode": { 1332 | "version": "2.3.0", 1333 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", 1334 | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", 1335 | "engines": { 1336 | "node": ">=6" 1337 | } 1338 | }, 1339 | "node_modules/qs": { 1340 | "version": "6.11.1", 1341 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", 1342 | "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==", 1343 | "dependencies": { 1344 | "side-channel": "^1.0.4" 1345 | }, 1346 | "engines": { 1347 | "node": ">=0.6" 1348 | }, 1349 | "funding": { 1350 | "url": "https://github.com/sponsors/ljharb" 1351 | } 1352 | }, 1353 | "node_modules/readable-stream": { 1354 | "version": "2.3.8", 1355 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", 1356 | "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", 1357 | "dependencies": { 1358 | "core-util-is": "~1.0.0", 1359 | "inherits": "~2.0.3", 1360 | "isarray": "~1.0.0", 1361 | "process-nextick-args": "~2.0.0", 1362 | "safe-buffer": "~5.1.1", 1363 | "string_decoder": "~1.1.1", 1364 | "util-deprecate": "~1.0.1" 1365 | } 1366 | }, 1367 | "node_modules/readdirp": { 1368 | "version": "3.6.0", 1369 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1370 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1371 | "optional": true, 1372 | "dependencies": { 1373 | "picomatch": "^2.2.1" 1374 | }, 1375 | "engines": { 1376 | "node": ">=8.10.0" 1377 | } 1378 | }, 1379 | "node_modules/request": { 1380 | "version": "2.88.2", 1381 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", 1382 | "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", 1383 | "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", 1384 | "peer": true, 1385 | "dependencies": { 1386 | "aws-sign2": "~0.7.0", 1387 | "aws4": "^1.8.0", 1388 | "caseless": "~0.12.0", 1389 | "combined-stream": "~1.0.6", 1390 | "extend": "~3.0.2", 1391 | "forever-agent": "~0.6.1", 1392 | "form-data": "~2.3.2", 1393 | "har-validator": "~5.1.3", 1394 | "http-signature": "~1.2.0", 1395 | "is-typedarray": "~1.0.0", 1396 | "isstream": "~0.1.2", 1397 | "json-stringify-safe": "~5.0.1", 1398 | "mime-types": "~2.1.19", 1399 | "oauth-sign": "~0.9.0", 1400 | "performance-now": "^2.1.0", 1401 | "qs": "~6.5.2", 1402 | "safe-buffer": "^5.1.2", 1403 | "tough-cookie": "~2.5.0", 1404 | "tunnel-agent": "^0.6.0", 1405 | "uuid": "^3.3.2" 1406 | }, 1407 | "engines": { 1408 | "node": ">= 6" 1409 | } 1410 | }, 1411 | "node_modules/request-promise": { 1412 | "version": "4.2.6", 1413 | "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", 1414 | "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", 1415 | "deprecated": "request-promise has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142", 1416 | "dependencies": { 1417 | "bluebird": "^3.5.0", 1418 | "request-promise-core": "1.1.4", 1419 | "stealthy-require": "^1.1.1", 1420 | "tough-cookie": "^2.3.3" 1421 | }, 1422 | "engines": { 1423 | "node": ">=0.10.0" 1424 | }, 1425 | "peerDependencies": { 1426 | "request": "^2.34" 1427 | } 1428 | }, 1429 | "node_modules/request-promise-core": { 1430 | "version": "1.1.4", 1431 | "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", 1432 | "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", 1433 | "dependencies": { 1434 | "lodash": "^4.17.19" 1435 | }, 1436 | "engines": { 1437 | "node": ">=0.10.0" 1438 | }, 1439 | "peerDependencies": { 1440 | "request": "^2.34" 1441 | } 1442 | }, 1443 | "node_modules/request/node_modules/form-data": { 1444 | "version": "2.3.3", 1445 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 1446 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 1447 | "peer": true, 1448 | "dependencies": { 1449 | "asynckit": "^0.4.0", 1450 | "combined-stream": "^1.0.6", 1451 | "mime-types": "^2.1.12" 1452 | }, 1453 | "engines": { 1454 | "node": ">= 0.12" 1455 | } 1456 | }, 1457 | "node_modules/request/node_modules/qs": { 1458 | "version": "6.5.3", 1459 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", 1460 | "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", 1461 | "peer": true, 1462 | "engines": { 1463 | "node": ">=0.6" 1464 | } 1465 | }, 1466 | "node_modules/safe-buffer": { 1467 | "version": "5.1.2", 1468 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1469 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1470 | }, 1471 | "node_modules/safer-buffer": { 1472 | "version": "2.1.2", 1473 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1474 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1475 | "peer": true 1476 | }, 1477 | "node_modules/semver": { 1478 | "version": "6.3.0", 1479 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1480 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1481 | "peer": true, 1482 | "bin": { 1483 | "semver": "bin/semver.js" 1484 | } 1485 | }, 1486 | "node_modules/side-channel": { 1487 | "version": "1.0.4", 1488 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 1489 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 1490 | "dependencies": { 1491 | "call-bind": "^1.0.0", 1492 | "get-intrinsic": "^1.0.2", 1493 | "object-inspect": "^1.9.0" 1494 | }, 1495 | "funding": { 1496 | "url": "https://github.com/sponsors/ljharb" 1497 | } 1498 | }, 1499 | "node_modules/slash": { 1500 | "version": "2.0.0", 1501 | "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", 1502 | "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", 1503 | "engines": { 1504 | "node": ">=6" 1505 | } 1506 | }, 1507 | "node_modules/sshpk": { 1508 | "version": "1.17.0", 1509 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", 1510 | "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", 1511 | "peer": true, 1512 | "dependencies": { 1513 | "asn1": "~0.2.3", 1514 | "assert-plus": "^1.0.0", 1515 | "bcrypt-pbkdf": "^1.0.0", 1516 | "dashdash": "^1.12.0", 1517 | "ecc-jsbn": "~0.1.1", 1518 | "getpass": "^0.1.1", 1519 | "jsbn": "~0.1.0", 1520 | "safer-buffer": "^2.0.2", 1521 | "tweetnacl": "~0.14.0" 1522 | }, 1523 | "bin": { 1524 | "sshpk-conv": "bin/sshpk-conv", 1525 | "sshpk-sign": "bin/sshpk-sign", 1526 | "sshpk-verify": "bin/sshpk-verify" 1527 | }, 1528 | "engines": { 1529 | "node": ">=0.10.0" 1530 | } 1531 | }, 1532 | "node_modules/stealthy-require": { 1533 | "version": "1.1.1", 1534 | "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", 1535 | "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==", 1536 | "engines": { 1537 | "node": ">=0.10.0" 1538 | } 1539 | }, 1540 | "node_modules/string_decoder": { 1541 | "version": "1.1.1", 1542 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1543 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1544 | "dependencies": { 1545 | "safe-buffer": "~5.1.0" 1546 | } 1547 | }, 1548 | "node_modules/superagent": { 1549 | "version": "3.7.0", 1550 | "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.7.0.tgz", 1551 | "integrity": "sha512-/8trxO6NbLx4YXb7IeeFTSmsQ35pQBiTBsLNvobZx7qBzBeHYvKCyIIhW2gNcWbLzYxPAjdgFbiepd8ypwC0Gw==", 1552 | "deprecated": "Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at .", 1553 | "dependencies": { 1554 | "component-emitter": "^1.2.0", 1555 | "cookiejar": "^2.1.0", 1556 | "debug": "^3.1.0", 1557 | "extend": "^3.0.0", 1558 | "form-data": "^2.3.1", 1559 | "formidable": "^1.1.1", 1560 | "methods": "^1.1.1", 1561 | "mime": "^1.4.1", 1562 | "qs": "^6.5.1", 1563 | "readable-stream": "^2.0.5" 1564 | }, 1565 | "engines": { 1566 | "node": ">= 4.0" 1567 | } 1568 | }, 1569 | "node_modules/superagent/node_modules/debug": { 1570 | "version": "3.2.7", 1571 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 1572 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 1573 | "dependencies": { 1574 | "ms": "^2.1.1" 1575 | } 1576 | }, 1577 | "node_modules/supports-color": { 1578 | "version": "5.5.0", 1579 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1580 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1581 | "peer": true, 1582 | "dependencies": { 1583 | "has-flag": "^3.0.0" 1584 | }, 1585 | "engines": { 1586 | "node": ">=4" 1587 | } 1588 | }, 1589 | "node_modules/to-fast-properties": { 1590 | "version": "2.0.0", 1591 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", 1592 | "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", 1593 | "peer": true, 1594 | "engines": { 1595 | "node": ">=4" 1596 | } 1597 | }, 1598 | "node_modules/to-regex-range": { 1599 | "version": "5.0.1", 1600 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1601 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1602 | "optional": true, 1603 | "dependencies": { 1604 | "is-number": "^7.0.0" 1605 | }, 1606 | "engines": { 1607 | "node": ">=8.0" 1608 | } 1609 | }, 1610 | "node_modules/tough-cookie": { 1611 | "version": "2.5.0", 1612 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", 1613 | "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", 1614 | "dependencies": { 1615 | "psl": "^1.1.28", 1616 | "punycode": "^2.1.1" 1617 | }, 1618 | "engines": { 1619 | "node": ">=0.8" 1620 | } 1621 | }, 1622 | "node_modules/tunnel-agent": { 1623 | "version": "0.6.0", 1624 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1625 | "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", 1626 | "peer": true, 1627 | "dependencies": { 1628 | "safe-buffer": "^5.0.1" 1629 | }, 1630 | "engines": { 1631 | "node": "*" 1632 | } 1633 | }, 1634 | "node_modules/tweetnacl": { 1635 | "version": "0.14.5", 1636 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 1637 | "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", 1638 | "peer": true 1639 | }, 1640 | "node_modules/update-browserslist-db": { 1641 | "version": "1.0.10", 1642 | "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", 1643 | "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", 1644 | "funding": [ 1645 | { 1646 | "type": "opencollective", 1647 | "url": "https://opencollective.com/browserslist" 1648 | }, 1649 | { 1650 | "type": "tidelift", 1651 | "url": "https://tidelift.com/funding/github/npm/browserslist" 1652 | } 1653 | ], 1654 | "peer": true, 1655 | "dependencies": { 1656 | "escalade": "^3.1.1", 1657 | "picocolors": "^1.0.0" 1658 | }, 1659 | "bin": { 1660 | "browserslist-lint": "cli.js" 1661 | }, 1662 | "peerDependencies": { 1663 | "browserslist": ">= 4.21.0" 1664 | } 1665 | }, 1666 | "node_modules/uri-js": { 1667 | "version": "4.4.1", 1668 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 1669 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 1670 | "peer": true, 1671 | "dependencies": { 1672 | "punycode": "^2.1.0" 1673 | } 1674 | }, 1675 | "node_modules/util-deprecate": { 1676 | "version": "1.0.2", 1677 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1678 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" 1679 | }, 1680 | "node_modules/uuid": { 1681 | "version": "3.4.0", 1682 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 1683 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", 1684 | "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", 1685 | "peer": true, 1686 | "bin": { 1687 | "uuid": "bin/uuid" 1688 | } 1689 | }, 1690 | "node_modules/verror": { 1691 | "version": "1.10.0", 1692 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 1693 | "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", 1694 | "engines": [ 1695 | "node >=0.6.0" 1696 | ], 1697 | "peer": true, 1698 | "dependencies": { 1699 | "assert-plus": "^1.0.0", 1700 | "core-util-is": "1.0.2", 1701 | "extsprintf": "^1.2.0" 1702 | } 1703 | }, 1704 | "node_modules/verror/node_modules/core-util-is": { 1705 | "version": "1.0.2", 1706 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 1707 | "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", 1708 | "peer": true 1709 | }, 1710 | "node_modules/wrappy": { 1711 | "version": "1.0.2", 1712 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1713 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 1714 | }, 1715 | "node_modules/yallist": { 1716 | "version": "3.1.1", 1717 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", 1718 | "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", 1719 | "peer": true 1720 | } 1721 | } 1722 | } 1723 | -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@arduino/arduino-iot-client": "^1.4.2", 4 | "request-promise": "^4.2.6" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/properties/create-property.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=create-property.js 4 | * Description: Below code will create property for thing via API on the bases of thing id 5 | */ 6 | 7 | var AIotApi = require('@arduino/arduino-iot-client'); 8 | var rp = require('request-promise'); 9 | var util = require("util"); 10 | 11 | async function getToken() { 12 | var options = { 13 | method: 'POST', 14 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 15 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 16 | json: true, 17 | form: { 18 | grant_type: 'client_credentials', 19 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 20 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 21 | audience: 'https://api2.arduino.cc/iot' 22 | } 23 | }; 24 | 25 | try { 26 | const response = await rp(options); 27 | return response['access_token']; 28 | } 29 | catch (error) { 30 | console.error("Failed getting an access token: " + error) 31 | } 32 | } 33 | 34 | async function CreateProperty(){ 35 | 36 | // Configure OAuth2 access token for authorization: oauth2 37 | var client = AIotApi.ApiClient.instance; 38 | var oauth2 = client.authentications['oauth2']; 39 | oauth2.accessToken = await getToken(); 40 | 41 | var api = new AIotApi.PropertiesV2Api() 42 | var thing_id="d99e244d-f245-4e27-9ead-717e52ac5a96"; 43 | var property = { 44 | 'name':'Temperature', 45 | 'variable_name':'temperature', 46 | 'permission':"READ_ONLY", 47 | 'persist':true, 48 | 'type':'TEMPERATURE_C', 49 | 'update_strategy':'ON_CHANGE' 50 | 51 | }; 52 | api.propertiesV2Create(thing_id, property).then(function(data) { 53 | console.log('Property Created successfully. Returned data: ' +util.inspect(data)); 54 | }, function(error) { 55 | console.error(error); 56 | }); 57 | } 58 | 59 | CreateProperty(); -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/properties/delete-property.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=delete-property.js 4 | * Description: Below code will delete the property for thing via API on the bases of thing id 5 | */ 6 | 7 | var AIotApi = require('@arduino/arduino-iot-client'); 8 | var rp = require('request-promise'); 9 | var util = require("util"); 10 | async function getToken() { 11 | var options = { 12 | method: 'POST', 13 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 14 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 15 | json: true, 16 | form: { 17 | grant_type: 'client_credentials', 18 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 19 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 20 | audience: 'https://api2.arduino.cc/iot' 21 | } 22 | }; 23 | 24 | try { 25 | const response = await rp(options); 26 | return response['access_token']; 27 | } 28 | catch (error) { 29 | console.error("Failed getting an access token: " + error) 30 | } 31 | } 32 | 33 | 34 | 35 | async function DeleteProperty(){ 36 | 37 | // Configure OAuth2 access token for authorization: oauth2 38 | var client = AIotApi.ApiClient.instance; 39 | var oauth2 = client.authentications['oauth2']; 40 | oauth2.accessToken = await getToken(); 41 | 42 | var api = new AIotApi.PropertiesV2Api() 43 | var thing_id="d99e244d-f245-4e27-9ead-717e52ac5a96"; 44 | var property_id="c4dc8f92-b62f-44df-9455-74cdd08041bc"; 45 | var options = { 46 | 'force':true 47 | }; 48 | api.propertiesV2Delete(thing_id,property_id, options).then(function(data) { 49 | console.log('Property Deleted successfully. Returned data: ' +data); 50 | }, function(error) { 51 | console.error(error); 52 | }); 53 | } 54 | 55 | DeleteProperty(); -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/properties/list-property.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=list-property.js 4 | * Description: Below code will show the list of property for thing via API on the bases of thing id 5 | */ 6 | 7 | var AIotApi = require('@arduino/arduino-iot-client'); 8 | var rp = require('request-promise'); 9 | var util = require("util"); 10 | async function getToken() { 11 | var options = { 12 | method: 'POST', 13 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 14 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 15 | json: true, 16 | form: { 17 | grant_type: 'client_credentials', 18 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 19 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 20 | audience: 'https://api2.arduino.cc/iot' 21 | } 22 | }; 23 | 24 | try { 25 | const response = await rp(options); 26 | return response['access_token']; 27 | } 28 | catch (error) { 29 | console.error("Failed getting an access token: " + error) 30 | } 31 | } 32 | 33 | 34 | 35 | async function ListProperty(){ 36 | 37 | // Configure OAuth2 access token for authorization: oauth2 38 | var client = AIotApi.ApiClient.instance; 39 | var oauth2 = client.authentications['oauth2']; 40 | oauth2.accessToken = await getToken(); 41 | 42 | var api = new AIotApi.PropertiesV2Api() 43 | var thing_id="6b6cd076-5859-4a6d-9b4e-18879893c6cb"; 44 | var options = { 45 | 'showDeleted':true 46 | 47 | }; 48 | api.propertiesV2List(thing_id, options).then(function(data) { 49 | console.log(' Returned data: ' +util.inspect(data)); 50 | }, function(error) { 51 | console.error(error); 52 | }); 53 | } 54 | 55 | ListProperty(); -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/properties/show-property.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=show-property.js 4 | * Description: Below code will display the properties of specific cloud variable via API on the bases of thing id & cloud variable id 5 | */ 6 | 7 | var AIotApi = require('@arduino/arduino-iot-client'); 8 | var rp = require('request-promise'); 9 | var util = require("util"); 10 | async function getToken() { 11 | var options = { 12 | method: 'POST', 13 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 14 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 15 | json: true, 16 | form: { 17 | grant_type: 'client_credentials', 18 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 19 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 20 | audience: 'https://api2.arduino.cc/iot' 21 | } 22 | }; 23 | 24 | try { 25 | const response = await rp(options); 26 | return response['access_token']; 27 | } 28 | catch (error) { 29 | console.error("Failed getting an access token: " + error) 30 | } 31 | } 32 | 33 | 34 | 35 | async function ShowProperty(){ 36 | 37 | // Configure OAuth2 access token for authorization: oauth2 38 | var client = AIotApi.ApiClient.instance; 39 | var oauth2 = client.authentications['oauth2']; 40 | oauth2.accessToken = await getToken(); 41 | 42 | var api = new AIotApi.PropertiesV2Api() 43 | var thing_id="6b6cd076-5859-4a6d-9b4e-18879893c6cb"; 44 | var property_id="b357a513-ad2b-4e1f-a76b-6dac078e36d5"; 45 | var opts = { 46 | 'showDeleted': true // {Boolean} If true, shows the soft deleted properties 47 | }; 48 | api.propertiesV2Show(thing_id, property_id, opts).then(function(data) { 49 | console.log('API called successfully. Returned data: ' + util.inspect(data)); 50 | }, function(error) { 51 | console.error(error); 52 | }); 53 | } 54 | 55 | ShowProperty(); -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/properties/update-property.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=update-property.js 4 | * Description: Below code will update the property for thing via API on the bases of thing id 5 | */ 6 | 7 | var AIotApi = require('@arduino/arduino-iot-client'); 8 | var rp = require('request-promise'); 9 | var util = require("util"); 10 | async function getToken() { 11 | var options = { 12 | method: 'POST', 13 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 14 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 15 | json: true, 16 | form: { 17 | grant_type: 'client_credentials', 18 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 19 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 20 | audience: 'https://api2.arduino.cc/iot' 21 | } 22 | }; 23 | 24 | try { 25 | const response = await rp(options); 26 | return response['access_token']; 27 | } 28 | catch (error) { 29 | console.error("Failed getting an access token: " + error) 30 | } 31 | } 32 | 33 | 34 | 35 | async function UpdateProperty(){ 36 | 37 | // Configure OAuth2 access token for authorization: oauth2 38 | var client = AIotApi.ApiClient.instance; 39 | var oauth2 = client.authentications['oauth2']; 40 | oauth2.accessToken = await getToken(); 41 | 42 | var api = new AIotApi.PropertiesV2Api() 43 | var thing_id="d99e244d-f245-4e27-9ead-717e52ac5a96"; 44 | var property_id="c4dc8f92-b62f-44df-9455-74cdd08041bc" 45 | var property = { 46 | 'name':'OutdoorTemperature', 47 | 'variable_name':'outdoorTemperature', 48 | 'permission':"READ_ONLY", 49 | 'persist':true, 50 | 'type':'TEMPERATURE_F', 51 | 'update_strategy':'ON_CHANGE' 52 | 53 | }; 54 | api.propertiesV2Update(thing_id,property_id, property).then(function(data) { 55 | console.log('Property Updated successfully. Returned data: ' +util.inspect(data)); 56 | }, function(error) { 57 | console.error(error); 58 | }); 59 | } 60 | 61 | UpdateProperty(); -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/start/main.js: -------------------------------------------------------------------------------- 1 | var IotApi = require('@arduino/arduino-iot-client'); 2 | var rp = require('request-promise'); 3 | 4 | async function getToken() { 5 | var options = { 6 | method: 'POST', 7 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 8 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 9 | json: true, 10 | form: { 11 | grant_type: 'client_credentials', 12 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 13 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 14 | audience: 'https://api2.arduino.cc/iot' 15 | } 16 | }; 17 | 18 | try { 19 | const response = await rp(options); 20 | return response['access_token']; 21 | } 22 | catch (error) { 23 | console.error("Failed getting an access token: " + error) 24 | } 25 | } 26 | 27 | async function ThingProperty(){ 28 | 29 | // Configure OAuth2 access token for authorization: oauth2 30 | var client = IotApi.ApiClient.instance; 31 | var oauth2 = client.authentications['oauth2']; 32 | oauth2.accessToken = await getToken(); 33 | 34 | var api = new IotApi.PropertiesV2Api() 35 | var id = "ef63111f-72bb-4826-84bb-02093d4d85f1"; // {String} The id of the thing 36 | var pid = "79decda8-ba31-4e62-b0b1-23e71e677013"; // {String} The id of the property 37 | var opts = { 38 | 'showDeleted': false // {Boolean} If true, shows the soft deleted properties 39 | }; 40 | api.propertiesV2Show(id, pid, opts).then(function(data) { 41 | console.log('API called successfully. Last Value of Property=' + data.last_value); 42 | }, function(error) { 43 | console.error(error); 44 | }); 45 | } 46 | ThingProperty(); -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/thing/create-sketch-thing.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=create-sketch-thing.js 4 | * Description: Below code will create a new sketch for thing via API 5 | */ 6 | 7 | //6e3d308c-dfb2-49ad-aa61-998227f214ab 8 | var AIotApi = require('@arduino/arduino-iot-client'); 9 | var rp = require('request-promise'); 10 | var util = require("util"); 11 | async function getToken() { 12 | var options = { 13 | method: 'POST', 14 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 15 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 16 | json: true, 17 | form: { 18 | grant_type: 'client_credentials', 19 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 20 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 21 | audience: 'https://api2.arduino.cc/iot' 22 | } 23 | }; 24 | 25 | try { 26 | const response = await rp(options); 27 | return response['access_token']; 28 | } 29 | catch (error) { 30 | console.error("Failed getting an access token: " + error) 31 | } 32 | } 33 | 34 | 35 | 36 | async function CreateSketch(){ 37 | 38 | // Configure OAuth2 access token for authorization: oauth2 39 | var client = AIotApi.ApiClient.instance; 40 | var oauth2 = client.authentications['oauth2']; 41 | oauth2.accessToken = await getToken(); 42 | 43 | var api = new AIotApi.ThingsV2Api() 44 | var id = 'd99e244d-f245-4e27-9ead-717e52ac5a96'; // {String} The id of the thing 45 | var thingSketch = {'sketch_version':'v1'}; // {ThingSketch} 46 | var opts = { 47 | 48 | }; 49 | 50 | api.thingsV2CreateSketch(id, thingSketch, opts).then(function(data) { 51 | console.log('Thing Sketch Created successfully. Returned data: ' + util.inspect(data)); 52 | }, function(error) { 53 | console.error(error); 54 | }); 55 | } 56 | 57 | CreateSketch(); -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/thing/create-thing.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=create-thing.js 4 | * Description: Below code will create a new thing via API 5 | */ 6 | 7 | var AIotApi = require('@arduino/arduino-iot-client'); 8 | var rp = require('request-promise'); 9 | var util = require("util"); 10 | async function getToken() { 11 | var options = { 12 | method: 'POST', 13 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 14 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 15 | json: true, 16 | form: { 17 | grant_type: 'client_credentials', 18 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 19 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 20 | audience: 'https://api2.arduino.cc/iot' 21 | } 22 | }; 23 | 24 | try { 25 | const response = await rp(options); 26 | return response['access_token']; 27 | } 28 | catch (error) { 29 | console.error("Failed getting an access token: " + error) 30 | } 31 | } 32 | 33 | 34 | 35 | async function CreateThing(){ 36 | 37 | // Configure OAuth2 access token for authorization: oauth2 38 | var client = AIotApi.ApiClient.instance; 39 | var oauth2 = client.authentications['oauth2']; 40 | oauth2.accessToken = await getToken(); 41 | 42 | var api = new AIotApi.ThingsV2Api() 43 | var thingCreate = {'name':'Sense the Env Thing Via API'}; // {ThingCreate} 44 | var opts = { 45 | 'force': true // {Boolean} If true, detach device from the other thing, and attach to this thing 46 | }; 47 | api.thingsV2Create(thingCreate, opts).then(function(data) { 48 | console.log('Thing Created successfully. Returned data: ' + util.inspect(data)); 49 | }, function(error) { 50 | console.error(error); 51 | }); 52 | } 53 | 54 | CreateThing(); -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/thing/delete-thing.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=delete-thing.js 4 | * Description: Below code will delete a thing via API on the bases of ID 5 | */ 6 | 7 | var AIotApi = require('@arduino/arduino-iot-client'); 8 | var rp = require('request-promise'); 9 | 10 | async function getToken() { 11 | var options = { 12 | method: 'POST', 13 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 14 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 15 | json: true, 16 | form: { 17 | grant_type: 'client_credentials', 18 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 19 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 20 | audience: 'https://api2.arduino.cc/iot' 21 | } 22 | }; 23 | 24 | try { 25 | const response = await rp(options); 26 | return response['access_token']; 27 | } 28 | catch (error) { 29 | console.error("Failed getting an access token: " + error) 30 | } 31 | } 32 | 33 | 34 | 35 | async function DeleteThing(){ 36 | 37 | // Configure OAuth2 access token for authorization: oauth2 38 | var client = AIotApi.ApiClient.instance; 39 | var oauth2 = client.authentications['oauth2']; 40 | oauth2.accessToken = await getToken(); 41 | 42 | var api = new AIotApi.ThingsV2Api() 43 | var id = 'ac9fc5fd-a946-406e-983d-715dcc2571b6'; // {String} The id of the thing 44 | var opts = { 45 | 'force': true // {Boolean} If true, detach device from the other thing, and attach to this thing 46 | }; 47 | api.thingsV2Delete(id, opts).then(function(data) { 48 | console.log('Thing Deleted successfully. Returned data: ' + data); 49 | }, function(error) { 50 | console.error(error); 51 | }); 52 | } 53 | 54 | 55 | DeleteThing(); -------------------------------------------------------------------------------- /Chapter#8 Working with the Arduino IoT Cloud SDK and Javascript/thing/list-thing.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arduino IoT Cloud JS SDK 3 | * File Name=list-thing.js 4 | * Description: Below code will list all thing via API on the bases of different options 5 | */ 6 | 7 | var AIotApi = require('@arduino/arduino-iot-client'); 8 | var rp = require('request-promise'); 9 | 10 | async function getToken() { 11 | var options = { 12 | method: 'POST', 13 | url: 'https://api2.arduino.cc/iot/v1/clients/token', 14 | headers: { 'content-type': 'application/x-www-form-urlencoded' }, 15 | json: true, 16 | form: { 17 | grant_type: 'client_credentials', 18 | client_id: 'YV0nrlEO6VRtWAc9xA3pWtxrYaMrjSJL', 19 | client_secret: 'ql4zjAEKoKIoWVRyRvHH6R141Ja7HKO7EaruZYaFjlRiLMrxgfu7QD4wdSTGGaMO', 20 | audience: 'https://api2.arduino.cc/iot' 21 | } 22 | }; 23 | 24 | try { 25 | const response = await rp(options); 26 | return response['access_token']; 27 | } 28 | catch (error) { 29 | console.error("Failed getting an access token: " + error) 30 | } 31 | } 32 | 33 | 34 | 35 | async function ListThing(){ 36 | 37 | // Configure OAuth2 access token for authorization: oauth2 38 | var client = AIotApi.ApiClient.instance; 39 | var oauth2 = client.authentications['oauth2']; 40 | oauth2.accessToken = await getToken(); 41 | 42 | var api = new AIotApi.ThingsV2Api() 43 | var opts = { 44 | 'acrossUserIds': false 45 | }; 46 | api.thingsV2List(opts).then(function(data) { 47 | for(var i=0;i 2 | #include 3 | 4 | OneWire ds18x20[] = {32,33,25,26}; 5 | const int oneWireCount = sizeof(ds18x20)/sizeof(OneWire); 6 | DallasTemperature sensor[oneWireCount]; 7 | 8 | float TempArray[4]; 9 | 10 | void setup() { 11 | 12 | Serial.begin(9600); // Initialize serial 13 | 14 | // Start up the library on all defined bus-wires 15 | DeviceAddress deviceAddress; 16 | for (int i = 0; i < oneWireCount; i++) {; 17 | sensor[i].setOneWire(&ds18x20[i]); 18 | sensor[i].begin(); 19 | if (sensor[i].getAddress(deviceAddress, 0)) sensor[i].setResolution(deviceAddress, 12); 20 | } 21 | 22 | 23 | } 24 | 25 | void loop() { 26 | Serial.print("Requesting temperatures..."); 27 | for (int i = 0; i < oneWireCount; i++) { 28 | sensor[i].requestTemperatures(); 29 | TempArray[i]=sensor[i].getTempCByIndex(0); 30 | delay(1000); //1 Second Delay 31 | } 32 | Serial.println("DONE"); 33 | 34 | 35 | for (int i = 0; i < 4; i++) { 36 | Serial.print("Temperature#"+String(i+1)+" "); 37 | Serial.print(TempArray[i]); 38 | Serial.print("\t"); 39 | Serial.println(""); 40 | } 41 | 42 | delay(5000); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Chapter#9 Project#4 Collecting Data from soil and Environment for Smart Farming/Soil-Moisture-Calibration/Soil-Moisture-Calibration.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //Adafruit_ADS1115 ads; /* Use this for the 16-bit version */ 4 | Adafruit_ADS1015 ads; /* Use this for the 12-bit version */ 5 | 6 | int AirValue[]={957,967,962,976}; 7 | int WaterValue[]={387,400,407,400}; 8 | 9 | void setup(void) 10 | { 11 | Serial.begin(9600); 12 | Serial.println("Hello!"); 13 | 14 | Serial.println("Getting single-ended readings from AIN0..3"); 15 | Serial.println("ADC Range: +/- 6.144V (1 bit = 3mV/ADS1015, 0.1875mV/ADS1115)"); 16 | 17 | if (!ads.begin()) { 18 | Serial.println("Failed to initialize ADS."); 19 | while (1); 20 | } 21 | } 22 | 23 | void loop(void) 24 | { 25 | int16_t adc0, adc1, adc2, adc3; 26 | float volts0, volts1, volts2, volts3; 27 | 28 | adc0 = getSoilMositure(0); 29 | volts0 = ads.computeVolts(adc0); 30 | delay(1000); 31 | adc1 = getSoilMositure(1); 32 | volts1 = ads.computeVolts(adc1); 33 | delay(1000); 34 | 35 | adc2 = getSoilMositure(2); 36 | volts2 = ads.computeVolts(adc2); 37 | delay(1000); 38 | 39 | adc3 = getSoilMositure(3); 40 | volts3 = ads.computeVolts(adc3); 41 | delay(1000); 42 | 43 | Serial.print("AIN0: "); Serial.print(adc0); Serial.print(" "); Serial.print(volts0); Serial.print("V");Serial.print(" "); Serial.print(map(adc0, WaterValue[0] ,AirValue[0], 100, 0));Serial.println("%"); 44 | Serial.print("AIN1: "); Serial.print(adc1); Serial.print(" "); Serial.print(volts1); Serial.print("V");Serial.print(" "); Serial.print(map(adc1, WaterValue[1],AirValue[1], 100, 0));Serial.println("%"); 45 | Serial.print("AIN2: "); Serial.print(adc2); Serial.print(" "); Serial.print(volts2); Serial.print("V");Serial.print(" "); Serial.print(map(adc2, WaterValue[2] ,AirValue[2], 100, 0));Serial.println("%"); 46 | Serial.print("AIN3: "); Serial.print(adc3); Serial.print(" "); Serial.print(volts3); Serial.print("V");Serial.print(" "); Serial.print(map(adc3, WaterValue[3] ,AirValue[3], 100, 0));Serial.println("%"); 47 | } 48 | 49 | float getSoilMositure(int Pin){ 50 | 51 | float SoilMositure=0; 52 | 53 | //loop 10 times for averaging 54 | for(int j = 0; j < 5; j++){ 55 | //SoilMositure+= analogRead(Pin); 56 | SoilMositure+= ads.readADC_SingleEnded(Pin); 57 | delay(1000); 58 | } 59 | 60 | //divide by 10 to get the average 61 | SoilMositure /= 5; 62 | 63 | 64 | return SoilMositure; 65 | } 66 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arduino IoT Cloud for Developers 2 | 3 | 4 | 5 | This is the code repository for [Arduino IoT Cloud for Developers](https://www.packtpub.com/product/arduino-iot-cloud-for-developers/9781837637171?utm_source=github&utm_medium=repository&utm_campaign=9781786461629), published by Packt. 6 | 7 | **Implement best practices to design and deploy simple-to-complex projects at reduced costs** 8 | 9 | ## What is this book about? 10 | From fundamental principles to advanced techniques, this comprehensive book equips you with the knowledge and skills needed to design and deploy IoT applications seamlessly. Explore cloud integration, best practices, and real-world projects to harness the full potential of IoT application development with the Arduino IoT Cloud. 11 | 12 | This book covers the following exciting features: 13 | * Gain a solid understanding of IoT fundamentals and concepts 14 | * Build creative IoT projects using Arduino MKR boards, Pulse sensors, and more 15 | * Master various communication technologies, including LoRaWAN and 3G/4G 16 | * Harness data exchange between IoT devices and cloud platforms using Zapier or IFTTT 17 | * Explore advanced features like scheduling, over-the-air updates, and scripting 18 | * Understand easy-to-sync properties across multiple devices with no-code 19 | * Develop voice-assisted home automation and heart rate tracking applications 20 | 21 | If you feel this book is for you, get your [copy](https://www.amazon.com/dp/1837637172) today! 22 | 23 | https://www.packtpub.com/ 25 | 26 | ## Instructions and Navigations 27 | All of the code is organized into folders. For example, Chapter02. 28 | 29 | The code will look like the following: 30 | ``` 31 | TinyGPSPlus gps; 32 | unsigned long previousMillis = 0; 33 | const long interval = 30000; //milliseconds 34 | ``` 35 | 36 | **Following is what you need for this book:** 37 | This book is for aspiring IoT developers and seasoned professionals eager to harness the potential of Arduino and cloud integration as well as technology enthusiasts, students, and hobbyists interested in experimenting with IoT technologies. Prior knowledge of basic electronics and embedded systems, cloud computing, Arduino, and programming languages like C and JavaScript is needed. 38 | 39 | With the following software and hardware list you can run all code files present in the book (Chapter 1-14). 40 | ### Software and Hardware List 41 | | Software required | OS required | 42 | | ------------------------------------ | ----------------------------------- | 43 | | Arduino IDE desktop version | Windows, macOS, or Linux | 44 | | Fritzing schematic design software | Windows, macOS, or Linux | 45 | | An Arduino IoT Cloud account or a Zapier account | N/A | 46 | | Amazon Alexa voice assistant | N/A | 47 | 48 | 49 | ### Related products 50 | * Architectural Patterns and Techniques for Developing IoT Solutions [[Packt]](https://www.packtpub.com/product/architectural-patterns-and-techniques-for-developing-iot-solutions/9781803245492?utm_source=github&utm_medium=repository&utm_campaign=9781803245492) [[Amazon]](https://www.amazon.com/dp/1803245492) 51 | 52 | * Building Smart Home Automation Solutions with Home Assistant [[Packt]](https://www.packtpub.com/product/building-smart-home-automation-solutions-with-home-assistant/9781801815291?utm_source=github&utm_medium=repository&utm_campaign=9781801815291) [[Amazon]](https://www.amazon.com/dp/1801815291) 53 | 54 | ## Get to Know the Author 55 | **Muhammad Afzal** 56 | is a senior software engineer with more than 14 years of experience of working on web-based and IoT systems in multinational organizations. He always enjoys working and solving real-world business problems with technology. He provides freelance services to IoT based product companies to write technical reviews and projects as well as providing consultancy to organizations. 57 | In his free time, Muhammad creates videos and courses for YouTube & Udemy. He also runs a maker movement in his region for young students to boost their interest to adopt the latest technologies. 58 | --------------------------------------------------------------------------------