Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Stephen Harrison
Published © CC BY-SA

Alexa Enabled USB Power Switch

Many devices are powered by USB power now, but few home automation systems provide USB power switching. "Alexa, turn off the ThingyStick!".

AdvancedFull instructions provided4 hours8,239
Alexa Enabled USB Power Switch

Things used in this project

Hardware components

Arduino MKR1000
Arduino MKR1000
×1
0.1uF 0805 Capacitor
×8
LED (generic)
LED (generic)
×4
Press button (Long)
×4
INA219 (soic 8)
×1
LM3526M
×2
USB Socket (Vertical)
×4
1k 0805 resistor
×4
0.1 Ohm Current Sense Resistor
×1
1uF 0805 Capacitor
×1

Software apps and online services

Alexa Skills Kit
Amazon Alexa Alexa Skills Kit
Tinamous
AWS Lambda
Amazon Web Services AWS Lambda

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)
Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

Enclosure - Base - All Connectors Open

This is the best bet if you don't know how you'll connect. It's got holes for the Arduino, terminal block and additional USB micro.

Enclosure - Base - All Holes - No Text

This is the all connectors version, but doesn't include the first layers of text which some printers may struggle with.

Lid - With Battery Compartment - No Feet

Lid - Battery Compartment - With Feet

Lid - No Battery - No Feet

This is the simplest version and quickest to print.

Lid - No Battery - With Feet

Schematics

PCB - All layers

PCB Bottom

PCB (Eagle)

Send this off to OSHPark or DirtyPCBs to get your own one made.

Schematic (Eagle)

Schematic

GitHub USB Power Switcher Repository

You want: Arduino/StandAlone/ folder and the 4 port version.

PCB - Top

Code

AlexaUsbSwitcher.ino

Arduino
This is the main file.
#include <MQTTClient.h>
#include <system.h>
#include <WiFi101.h>
#include <Adafruit_INA219.h>
// Provide your own Secrets.h with WiFi and Tinamous definitions in it.
#include "Secrets.h"

// ================================
/*
#define MAX_USB_PORTS 2

// 2 Port board.
int led_pin[MAX_USB_PORTS][2] = {{A5, A6},{0,1}};
int switch_pin[] = {A0, A1};

// Usb switch B channel -> pin 5 == USB1
int usb_enable_pin[] = {2, 5};
int usb_fault_pin[] = {3, 4};
bool usb_port_state[] = {false, false};
bool usb_power_mode[] = {0, 0, 1, 1};
*/

// ---------------------------------

// 4 Port board.
#define MAX_USB_PORTS 4

// The 2  port board has bi-color LEDs, 4 port doesn't so use same pin......
// LEDs: TX, Rx, D7, D6 (1-4)
int led_pin[MAX_USB_PORTS][2] = {{14, 14}, {13,13}, {7,7}, {6,6}};
int switch_pin[] = {A0, A1, A2, A3};

// USB Enable pins, D1, D3, D4, D5 (not in that order)
int usb_enable_pin[] = {5, 4, 1, 3};
// Single fault pin (D2)
int usb_fault_pin[] = {2, 2, 2, 2};

bool usb_port_state[] = {false, false, false, false};

// Mode: 0 - Switch off as requested.
// Mode: 1 - Switch off, then on after a delay (useful for LED lights that have touch controls).
int usb_power_mode[] = {1, 0, 0, 0};

// ================================

// Automation options.
// time (millis) that the USB port should be switched on/off at.
// zero indicates ignore.
unsigned long usb_power_switch_on_at[] = {0, 0, 0, 0};

// Set > 0 to get processed on first loop.
// Side effect is switching them off that those in smart power 
// mode will schedule to come back on again).
unsigned long usb_power_switch_off_at[] = {1, 1, 1, 1};

// Current monitor INA219
Adafruit_INA219 ina219;

// Flag to indicate if one or more USB ports has a fault.
bool has_usb_fault = false;

// Measured power .
float shunt_voltage = 0;
float bus_voltage = 0;
float current_mA = 0;
float load_voltage = 0;
float power_mW = 0;

// Min/max 
float max_current_mA =0;
float max_busvoltage = 0;
float min_busvoltage = 20;

// track power usage.
unsigned long last_measurement_time = 0;

bool power_failed = false;
bool over_current = false;

// MQTT publishing.
// Probably want it quicker when powering devices.
// or slower when not!
int update_interval_seconds = 20;
unsigned long next_message_send_at = 0;

// =================================================
// Main setup entry point
// =================================================
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);
  
  for (int channel=0; channel<MAX_USB_PORTS; channel++) {
    setupChannel(channel);
  }

  delay(2000);
  showSetupStageCompleted(1);
 
  //Initialize serial and wait for port to open:
  Serial.begin(115200);
  // Give us a small delay to open the serial monitor...
  delay(3000);
  showSetupStageCompleted(2);


  // Setup the current sensor.
  ina219.begin();

  setupWiFi();
  showSetupStageCompleted(3);

  setupMqtt();
  showSetupStageCompleted(4);

  // Give it a few seconds to warm up!
  sentNextPublishAt(5);

  Serial.println("Alexa Enabled USB Power Switched v0.4 Setup Complete");
}

// Setup the IO pins for the usb port.
void setupChannel(int channel) {
  
  // Setup the LEDs.
  pinMode(led_pin[channel][0], OUTPUT);
  digitalWrite(led_pin[channel][0], LOW);

  if (led_pin[channel][0] != led_pin[channel][1]) {
    pinMode(led_pin[channel][1], OUTPUT);
    digitalWrite(led_pin[channel][1], LOW);
  }

  // Setup the Switches
  pinMode(switch_pin[channel], INPUT_PULLUP);

  pinMode(usb_enable_pin[channel], OUTPUT);
  digitalWrite(usb_enable_pin[channel], HIGH);

  // This is the same pin on all channels for the 4 channel device.
  pinMode(usb_fault_pin[channel], INPUT_PULLUP);
}

// Show setup state 1..4 complete 
// can't do steps 3 & 4 on 2 port board.
void showSetupStageCompleted(int stage) {
  if (stage > MAX_USB_PORTS) {
    return;
  }

  // Light up the LED (1..4) based on the setup progress.
  SetLeds(stage-1 , true, true);
}


// ===================================================
// Main Loop
// ===================================================
void loop() {

  // 4 port device, Debug LED is port 4 LED.
  // if any port 4 is on, then don't switch off the LED.
  // with all 4 ports off, the debug LED can blink as it likes...
  if (!hasPoweredPorts()) {
    digitalWrite(LED_BUILTIN, LOW);
  }

  // Check for a fault.
  bool faulted = false;
  for (int channel = 0; channel < MAX_USB_PORTS; channel++) {
    if (checkFault(channel)) {
      faulted = true;
    }

    // Lets us clear the has_usb_fault if ALL of the channels are not faulted.
    has_usb_fault = faulted;
    checkSwitchPressed(channel);
  }

  // Do any automation (e.g. switch on at a certain time)
  runAutomation();

  // Check the current, voltage and all that.
  readCurrent();

  // Check for a power fail.
  checkPowerSupply();
  
  doDelay();

  mqttLoop();

  sendStatus();
}

void doDelay() {
  if (hasPoweredPorts()) {
    delay(100);
    return;
  }

  // Debug only. LED is on Port 4 LED so is shown to the user when 
  // all ports are off.
  //
  // Blinky only when in slow mode so we don't have to delay the
  // reads for the user to see the blinkyness.
  // No ports on, don't update so often.
  delay(100);
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
}

// Check fr user pressing the switch to turn on a port.
void checkSwitchPressed(int channel) {
  if (isSwitchPressed(channel)) {
    // Toggle the USB power
    setUsb(channel, !usb_port_state[channel]);
  }
}

// Switch press logic to debounce the switch
bool isSwitchPressed(int channel) {
  // Switch is active low.

  // Debounce delay to ensure the switch is properly pressed.
  // Switch is active low. false = pressed.
  if (digitalRead(switch_pin[channel])) {
    return false;
  }

  // wait to see if it's still pressed after 0.2s
  delay(50);

  if (!digitalRead(switch_pin[channel])) {
    // Little debounce...
    delay(100);
    return true;
  }
  return false;
}

// Read the INA219 (Voltage, Current)
void readCurrent() {
  
  shunt_voltage = ina219.getShuntVoltage_mV();
  bus_voltage = ina219.getBusVoltage_V();
  current_mA = ina219.getCurrent_mA();
  //power_mW = ina219.getPower_mW();
  load_voltage = bus_voltage + (shunt_voltage / 1000);
  // record the measurement time so we can compute 
  // power*time usage.
  last_measurement_time = millis();

  if (current_mA > max_current_mA) {
    max_current_mA = current_mA;
  }

  if (bus_voltage > max_busvoltage) {
    max_busvoltage = bus_voltage;
  }

  if (bus_voltage < min_busvoltage) {
    min_busvoltage = bus_voltage;
  }
  
  printPowerSkinny();
}

// Check we have power input, it's not got a significant voltage drop
// and we're not overloading the input.
void checkPowerSupply() {
  // Higher bus voltage for restored to stop it 
  // going back and forth at 4.19...
  if (power_failed && bus_voltage > 4.5) {
    Serial.print("External power restored. Bus voltage: "); 
    Serial.print(bus_voltage); 
    Serial.println(" V");

    publishTinamousStatus("External power has been restored.");
    power_failed = false;
  }
  
  if (bus_voltage < 4.2 && !power_failed) {
    Serial.print("External power failed! Bus voltage: "); 
    Serial.print(bus_voltage); 
    Serial.println(" V.");

    publishTinamousStatus("External power lost!");
    power_failed = true;
  }

  if (over_current && current_mA < 1500) {
    publishTinamousStatus("Current fault cleared!");
    over_current = false;
  }

  if (current_mA > 2000 && !over_current) {
    // Overload!
    publishTinamousStatus("Over Current!");
    over_current = true;
  } 
}

void printPowerWide() {
  Serial.print("Bus Voltage:\t"); 
  Serial.print(bus_voltage); 
  Serial.print(" V\t");
  
  Serial.print("Current:    \t"); 
  Serial.print(current_mA); 
  Serial.print(" mA\t");
  
  Serial.print("Max Current:\t"); 
  Serial.print(max_current_mA); 
  Serial.print(" mA\t");
  
  Serial.print("Min Voltage:\t");
  Serial.print(min_busvoltage); 
  Serial.print(" V\t");
  
  Serial.print("Max Voltage:\t");
  Serial.print(max_busvoltage); 
  Serial.print(" V\t");

  Serial.println();
}

void printPowerSkinny() {
  Serial.print(bus_voltage); 
  Serial.print("\t");
  
  Serial.print(current_mA); 
  Serial.print("\t\t");
  
  Serial.print(max_current_mA); 
  Serial.print("\t\t");
  
  Serial.print(min_busvoltage); 
  Serial.print("\t");
  
  Serial.print(max_busvoltage); 
  Serial.print("\t");

  Serial.print("[");
  for (int channel=0; channel<MAX_USB_PORTS; channel++) {
    Serial.print(usb_port_state[channel] ? "1" : "0" ); 
    Serial.print("\t");
  }
  Serial.print("]\t");

  Serial.print(millis()); 
  Serial.print("\t");

  Serial.println();
}

void resetStats() {
  max_current_mA =0;
  max_busvoltage = 0;
  min_busvoltage = 20;
}

void sentNextPublishAt(int secondsTime) {
  next_message_send_at = millis() + (secondsTime * 1000);
}

// ============================================
// Send the device status.
// ============================================
void sendStatus() {
  if (millis() > next_message_send_at) { 
    Serial.println("------------------------"); 
    Serial.println("MQTT publish measurements"); 

    if (power_failed) {
      // reduce how often we send when the power
      // has failed to preserve battery power.
      sentNextPublishAt(update_interval_seconds * 10);
    } else {
       sentNextPublishAt(update_interval_seconds);
    }
    
    // And do one as senml...
    String senml = "{'e':[";
    // Voltage
    senml = senml + "{'n':'busVoltage'";
    senml = senml + ", 'v':";
    senml = senml + String(bus_voltage);
    senml = senml + ", 'u':'V'}";

    // Max voltage
    senml = senml + ",{'n':'maxBusVoltage'";
    senml = senml + ", 'v':";
    senml = senml + String(max_busvoltage);
    senml = senml + ", 'u':'V'}";

    // Min voltage
    senml = senml + ",{'n':'minBusVoltage'";
    senml = senml + ", 'v':";
    senml = senml + String(min_busvoltage);
    senml = senml + ", 'u':'V'}";
        
    // Current
    senml = senml + ",{'n':'Current'";
    senml = senml + ", 'v':";
    senml = senml + String(current_mA);
    senml = senml + ", 'u':'mA'}";
    
    // Max current
    senml = senml + ",{'n':'MaxCurrent'";
    senml = senml + ", 'v':'";
    senml = senml + String(max_current_mA);
    senml = senml + "', 'u':'mA'}";
    
    // mAh consumed...
    senml = senml + ",{'n':'mAh'";
    senml = senml + ", 'v':";
    senml = senml + String(0); // TODO!
    senml = senml + ", 'u':'mAh'}";
   
    senml = senml + ",{'n':'powerState";
    senml = senml + "', 'bv':";
    if (isPowered()) {
      senml = senml +  "true";
    } else {
      senml = senml +  "false";
    }
    senml = senml + "}";
  

    for (int channel=0; channel<MAX_USB_PORTS; channel++) {
      senml = senml + ",{'n':'Port-";
      senml = senml + String(channel+1);
      senml = senml + "', 'v':";
      senml = senml + String(usb_port_state[channel]);
      senml = senml + "}";
    }
        
    senml = senml +  "]}";
    publishTinamousSenMLMeasurements(senml);
    Serial.println("------------------------"); 
    Serial.println(); 
  }
}

bool isPowered() {
  return !power_failed;
}

void runAutomation() {
  for (int channel =0; channel < MAX_USB_PORTS; channel++) {
    // Check to see if the port should be powered on automatically
    unsigned long onAt = usb_power_switch_on_at[channel];
    if (onAt > 0 && onAt < millis()) {
      Serial.print("Auto on for port: ");
      Serial.println(channel + 1);
      
      setUsb(channel, true);
      usb_power_switch_on_at[channel] = 0;
    }

    // Check to see if the port should be powered off automatically
    unsigned long offAt = usb_power_switch_off_at[channel]; 
    if (offAt > 0 && offAt < millis()) {
      Serial.print("Auto off for port: ");
      Serial.println(channel + 1);
      
      setUsb(channel, false);
      usb_power_switch_off_at[channel] = 0;
    }
  }
}

TinamousMQTTClient.ino

Arduino
This file handled the MQTT connectivity (i.e. it's the bit that responds to Alexa commands).
// ======================================
// Tinamous connectivity via MQTT
// ======================================
#include <MQTTClient.h>
#include <system.h>
#include "secrets.h"

// WiFi and MQTT settings in Secrets.h
// Be sure to use WiFiSSLClient for an SSL connection.
// for a non ssl (port 1883) use regular WiFiClient.
//WiFiClient networkClient; 
WiFiSSLClient networkClient; 

// https://github.com/256dpi/arduino-mqtt
// Specifying 4096 bytes buffer size
MQTTClient mqttClient(4096); 

// If we have been connected since powered up 
bool was_connected = false;
String senml = "";
unsigned long nextSendMeasurementsAt = 0;

// =================================================
// Setup the MQTT connection information
// =================================================
bool setupMqtt() {
  senml.reserve(4096);
  Serial.print("Connecting to Tinamous MQTT Server on port:");
  Serial.println(MQTT_SERVERPORT);
  Serial.print("Server:");
  Serial.println(MQTT_SERVER);
  mqttClient.begin(MQTT_SERVER, MQTT_SERVERPORT, networkClient);

  // Handle received messages.
  mqttClient.onMessage(messageReceived);

  connectToMqttServer();
}

// =================================================
// Connect to the MQTT server. This can be called 
// repeatedly and will be ignored if already connected
// =================================================
bool connectToMqttServer() { 
  if (mqttClient.connected()) {
    return true;
  }

  Serial.println("Reconnecting...."); 

  Serial.println("checking wifi..."); 
  if (WiFi.status() != WL_CONNECTED) { 
    Serial.print("WiFi Not Connected. Status: "); 
    Serial.print(WiFi.status(), HEX); 
    Serial.println();
    delay(10000);
    return false;
  } 
 
  Serial.println("Connecting to MQTT Server..."); 
  
  if (!mqttClient.connect(MQTT_CLIENT_ID, MQTT_USERNAME, MQTT_PASSWORD)) { 
    Serial.println("Failed to connect to MQTT Server."); 
    Serial.print("Error: "); 
    Serial.print(mqttClient.lastError()); 
    Serial.print(", Return Code: "); 
    Serial.print(mqttClient.returnCode()); 
    Serial.println(); 

    if (mqttClient.lastError() == LWMQTT_CONNECTION_DENIED) {
      Serial.println("Access denied. Check your username and password. Username should be 'DeviceName.AccountName' e.g. MySensor.MyHome"); 
    }

    if (mqttClient.lastError() == -6) {
      Serial.println("Check your Arduino has the SSL Certificate loaded for Tinmaous.com"); 
      // Load the Firmware Updater sketch onto the Arduino.
      // Use the Tools -> WiFi Firmware Updater utility
    }

    // Wait 10s before it gets re-tried.
    delay(10000); 
    return false;
  } 
 
  Serial.println("Connected to Tinamous MQTT!"); 
 
  mqttClient.subscribe("/Tinamous/V1/Status.To/" DEVICE_USERNAME); 
  Serial.println("Subscribed to status.to topic."); 
  
  // Say Hi.
  publishTinamousStatus("Hello! Usb switch is now connected. @ me with help for help.");

  was_connected = true;
  return true;
} 

// =================================================
// Loop for mqtt processing.
// =================================================
void mqttLoop() {
  // Call anyway, does nothing if already connected.
  connectToMqttServer();
  
  mqttClient.loop(); 
}

// =================================================
// Publish a status message on the Tinamous timeline
// =================================================
void publishTinamousStatus(String message) {
  Serial.println("Status: " + message);
  mqttClient.publish("/Tinamous/V1/Status", message); 
}

// =================================================
// Publish measurements using the plain json format
// =================================================
void publishTinamousJsonMeasurements(String json) {
  Serial.println("Measurement: " + json);
  mqttClient.publish("/Tinamous/V1/Measurements/Json", json); 
}

// =================================================
// Publish measurements using senml json format
// =================================================
void publishTinamousSenMLMeasurements(String senml) {
  Serial.println("SenML Measurement: " + senml);
  mqttClient.publish("/Tinamous/V1/Measurements/SenML", senml); 
  if (mqttClient.lastError() != 0) {
    Serial.print("MQTT Error: "); 
    Serial.print(mqttClient.lastError()); 
    Serial.println(); 
  }
  Serial.println("Done.");
}
// =================================================
// Message received from the MQTT server
// =================================================
void messageReceived(String &topic, String &payload) { 
  Serial.println("Message from Tinamous on topic: " + topic + " - " + payload); 

  // If it starts with @ it's a status message to this device.
  if (payload.startsWith("@")) {
    payload.toLowerCase();
    if (handleStatusMessage(payload)) {
      Serial.println("@ me status message handled.");
      return;
    }
  } 

  // Didn't get an expected command, so the message was to us.
  // Publish a help message.
  publishTinamousStatus("Hello! Sorry I didn't understand the message. @ me with help for help.");
} 

// =================================================
// Message was a Status Post (probably Alexa)
// =================================================
bool handleStatusMessage(String payload) {
char buffer[25];

   // for 1..4 (maps to 0..3)
  for (int port = 0; port <MAX_USB_PORTS; port++) {
    sprintf(buffer, "turn on port-%01d", port + 1);
    
    if (payload.indexOf(buffer)> 0) {
      Serial.print("Turn on port ");
      Serial.println(port);
      setUsb(port, true);
      return true;
    }

    sprintf(buffer, "turn off port-%01d", port + 1);
    if (payload.indexOf(buffer)> 0) {
      Serial.print("Turn off port ");
      Serial.println(port);
      setUsb(port, false);
      return true;
    }
  }

  // No port specified, turn on all.
  if (payload.indexOf("turn on")> 0) {
    allOn();
    return true;
  }

  if (payload.indexOf("turn off")> 0) {
    allOff();
    return true;
  }

  if (payload.indexOf("help")> 0) {
    Serial.println("Sending help...");
    publishTinamousStatus(
    "Send a message to me (@" DEVICE_USERNAME ") then:" 
    "'Turn on Port-1' to turn on usb port 1,"
    "'Turn off Port-1' to turn off usb port 1,"
    "'Turn on' to turn on all usb ports,"
    "'Turn off' to turn off all usb ports,"
    " \n* Port number can be 1, 2, 3 or 4."
    );
    return true;
  }

  Serial.print("Unknown status message: ");
  Serial.println(payload);
  
  return false;
}

UsbControl.ino

Arduino
This file is responsible for the iterations with the USB power switching.
// ======================================
// USB Port power control
// and indication.
// ======================================

// Determine if one or more of the ports is powered
bool hasPoweredPorts() {
  for (int channel = 0; channel < MAX_USB_PORTS; channel++) {
    if (usb_port_state[channel]) {
      return true;
    }
  }
  return false;
}

// Check if the USB devices have a fault (we can't
// tell which one in the 4 port 
bool checkFault(int channel) {
  if (!digitalRead(usb_fault_pin[channel])) {
    // 4 port has a single fault indicator, don't keep checking
    if (has_usb_fault) {
      return true;
    }
    
    Serial.print("FAULT! usb: ");
    Serial.println(channel);

    // Switch off the USB channel.
    setUsb(channel, false);
    
    // Make the LEDs red.
    SetLeds(channel, true, false);

    if (!has_usb_fault) {
      // TODO: Send the message once only!
      //String message = "Fault detected on USB Port ";
      //message = message + String(channel + 1);
      //publishTinamousStatus(message);
      has_usb_fault = true;
    }

    return true;
  }
  return false;
}

// Switch on ALL of the USB ports
void allOn() {
  for(int channel =0; channel < MAX_USB_PORTS; channel++) {
    setUsb(channel, true);
  }
}

// Switch off ALL of the USB ports
void allOff() {
  for(int channel =0; channel < MAX_USB_PORTS; channel++) {
    setUsb(channel, true);
  }
}

// ================================================
// Set the USB output state
// ================================================
void setUsb(int channel, bool on) {
  Serial.print("Switch USB channel ");
  Serial.print(channel);
  Serial.print(" to ");
  Serial.println(on);
  
  if (on) {
    resetStats();
    SetLeds(channel, on, true);
    digitalWrite(usb_enable_pin[channel], LOW);
  } else {
    SetLeds(channel, on, true);
    digitalWrite(usb_enable_pin[channel], HIGH);
  }

  usb_port_state[channel] = on;

  String message = "USB Port ";
  message = message + String(channel + 1);
  message = message + " is now ";
  if (on) {
    message = message + "enabled.";
  } else {
    message = message + "disabled.";
  }
  publishTinamousStatus(message);
  
  // force a send of the current/voltage after a second or few.
  sentNextPublishAt(1);

  // If the channel mode is to cycle off then on for 
  // an off signal, switch the channel back on after a few seconds delay.
  if (!on && usb_power_mode[channel] == 1) {
    // Schedule the channel to come back on in n seconds.
    usb_power_switch_on_at[channel] = millis() + 5000;
  }
}

// ================================================
// Set the state leds to indicate channel on/off
// They are not connected to the USB switch so 
// can be run independantly.
// ================================================
void SetLeds(int channel, bool on, bool green) {
  if (!on) {
    digitalWrite(led_pin[channel][0], LOW);
    digitalWrite(led_pin[channel][1], LOW);
    return;
  }

  if (led_pin[channel][0] == led_pin[channel][1]) {
    // 4 Port uses single color LED.
    // We don't have a way to show faultes (other than flashing LEDs).
    digitalWrite(led_pin[channel][0], HIGH);
  } else {
    // 2 Port uses Bi-color LED and individual faults
    // so show red/green based on status.
    if (green) {
      digitalWrite(led_pin[channel][0], HIGH);
      digitalWrite(led_pin[channel][1], LOW);
    } else {
      digitalWrite(led_pin[channel][0], LOW);
      digitalWrite(led_pin[channel][1], HIGH);
    }
  }
}

WiFiClient.ino

Arduino
This file deals with WiFi Connectivity
// ======================================
// WiFi handling
// ======================================
#include "Secrets.h" 

char ssid[] = SECRET_SSID;    
char pass[] = SECRET_PASS;    
int status = WL_IDLE_STATUS; 

void setupWiFi() {
  Serial.println("Connecting to WiFi...");

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue:
    while (true);
  }

  // attempt to connect to WiFi network:
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }

  // you're connected now, so print out the data:
  Serial.println("You're connected to the network");
  printCurrentNet();
  printWiFiData();
}

// ---------------------------------------
// WiFi
void printWiFiData() {
  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  Serial.println(ip);

  // print your MAC address:
  byte mac[6];
  WiFi.macAddress(mac);
  Serial.print("MAC address: ");
  Serial.print(mac[5], HEX);
  Serial.print(":");
  Serial.print(mac[4], HEX);
  Serial.print(":");
  Serial.print(mac[3], HEX);
  Serial.print(":");
  Serial.print(mac[2], HEX);
  Serial.print(":");
  Serial.print(mac[1], HEX);
  Serial.print(":");
  Serial.println(mac[0], HEX);

}

void printCurrentNet() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print the MAC address of the router you're attached to:
  byte bssid[6];
  WiFi.BSSID(bssid);
  Serial.print("BSSID: ");
  Serial.print(bssid[5], HEX);
  Serial.print(":");
  Serial.print(bssid[4], HEX);
  Serial.print(":");
  Serial.print(bssid[3], HEX);
  Serial.print(":");
  Serial.print(bssid[2], HEX);
  Serial.print(":");
  Serial.print(bssid[1], HEX);
  Serial.print(":");
  Serial.println(bssid[0], HEX);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.println(rssi);

  // print the encryption type:
  byte encryption = WiFi.encryptionType();
  Serial.print("Encryption Type:");
  Serial.println(encryption, HEX);
  Serial.println();
}


String hostName = "www.google.com";

void doPing() {
  Serial.print("Pinging ");
  Serial.print(hostName);
  Serial.print(": ");

  int pingResult = WiFi.ping(hostName);

  if (pingResult >= 0) {
    Serial.print("SUCCESS! RTT = ");
    Serial.print(pingResult);
    Serial.println(" ms");
  } else {
    Serial.print("FAILED! Error code: ");
    Serial.println(pingResult);
  }
}
 
void reconnectWiFi() {
  // attempt to reconnect to WiFi network if the connection was lost:
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network:
    status = WiFi.begin(ssid, pass);

    if (status == WL_CONNECTED) {
      Serial.print("You're re-connected to the network");
      printCurrentNet();
      printWiFiData();
      return;
    }

    delay(5000);
  } 
}

Secrets.h

Arduino
You need to update this with your own settings.
#define SECRET_SSID "<WiFi access point>"
#define SECRET_PASS "<WiFi Password>"

/************************* Tinamous MQTT Setup *********************************/

#define MQTT_SERVER      "<Your account name>.tinamous.com"
#define MQTT_SERVERPORT  8883   
#define MQTT_USERNAME    "<Device Username>.<Your account name>"
#define MQTT_PASSWORD    "The devices password"
#define MQTT_CLIENT_ID   "A random client id"
#define DEVICE_USERNAME  "<Device Username>"

Credits

Stephen Harrison

Stephen Harrison

18 projects • 51 followers
Founder of Tinamous.com, software developer, hardware tinkerer, dyslexic. @TinamousSteve

Comments