Daniel Martin
Published © GPL3+

Smart Ambient Lighting

Ambient lighting that smartly responds to your moods and needs.

BeginnerFull instructions provided10 hours6,922
Smart Ambient Lighting

Things used in this project

Hardware components

SparkFun ESP8266 Thing - Dev Board
SparkFun ESP8266 Thing - Dev Board
×1
Arduino Yun
Arduino Yun
×1
Adafruit RGB LED Weatherproof flexi-strip
×1
Adafruit N-channel power MOSFET 30V/60A (IRLB8721)
×3
Micro Connectors 25' 22AWG 4-conductor Stranded Unshielded Cable
×1
Shaxon ST14-25WT 25-Feet on Spool Stranded Copper Wire, White
×1
Adafruit 12V 5A switching power supply
×1
SparkFun Mini Photocell
×6
SparkFun Solder-able Breadboard
×1
SparkFun Breadboard - Self-Adhesive (White)
×1
SparkFun Jumper Wires Standard 7" M/M - 30 AWG (30 Pack)
×1
SparkFun Jumper Wires Premium 6" M/F Pack of 10
×2
PIR Motion Sensor (generic)
PIR Motion Sensor (generic)
×1
Parallax IR Transmitter Assembly Kit
×1
Parallax Infrared Receiver
×1
10k Ohm Resistor
×2
2k Ohm Resistor
×1
Resistor 220 ohm
Resistor 220 ohm
×1
SparkFun LED - RGB Addressable, PTH, 8mm (5 Pack)
×1

Software apps and online services

Cayenne
myDevices Cayenne

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Code

Arduino Yun's 32U4 Code

Arduino
This is the Light Control Module which uses a PIR sensor, a buzzer, and some photocells to drive the LED strip. The 32U4 chip receives a code from the AR9331 processor via the Bridge.
/* This is the Arduino code for the Smart Ambient Lighting Project
 *  Upload this code to an Arduino Yun.
 *  
 *  The microcontroller is connected to an RGB LED Strip, a PIR
 *  Sensor, some photocells, and a buzzer. When motion is detected
 *  and the room is dimly lit, the LED strip will turn on until 
 *  motion is no longer detected. Then, the buzzer will sound and 
 *  the lights will turn off. If it receives a signal from the 
 *  Linux side of the Arduino through Bridge, the lights will turn 
 *  on according to the temperature outside. This program is also 
 *  compatible with Cayenne.
 *  
 * Created by Daniel Martin
 */

 
#define RED 3           // Pin connected to gate of Red Transistor (must be PWM)
#define GREEN 5         // Pin connected to gate of Green Transistor (must be PWM)
#define BLUE 9          // Pin connected to gate of Blue Transistor (must be PWM)

// Virtual Pins for Cayenne sliders to control the lights
#define REDVP 3
#define GREENVP 4
#define BLUEVP 5


int irDistance = 8;
int irDistPlus = 5;
int piezoPin = 4;       // pin for buzzer

// threshold for light intensity
// increase the value if you want the lights to turn on even if the room is lit
// decrease the value if you want the lights to turn on only if it's very dark
int threshold = 700;  
 
char Dvalue[2];     // variable to take in temp-range value from ESP8266


//When light is on, wait 60s 
//After time limit, wait 30s and check if the number of movements is greater than PIRNUM
int pirNum = 0;     // initialize pirNum to 0
unsigned long extraTimeLim = 30000;     
unsigned long timeLim = 60000;
int PIRNUM = 0;
int nextmode = 0;

#define CAYENNE_PRINT Serial  // Comment this out to disable prints and save space

#include <stdio.h>

#include <Console.h>
#include <CayenneYun.h>

// This token is found in the configuration of your Yn in cayenne.mydevices.com
char token[] = "**********";

unsigned long timer;
unsigned long extraTime;


int photoPin = 0;       // Analog pin connected to photocells
int photoReading = 0;
int pirPin = 7;         // Digital pin connected to PIR
int pirVal = 0;
bool isOn = false;      // Light is off

// Used in Cayenne's checkSensor function
int previousState = -1;
int currentState = -1;
unsigned long previousMillis = 0;

int bright = 255;


void setup() {

  memset(Dvalue, 0, 2);       //set memory for variable which will be received from ESP8266

  Cayenne.begin(token);       // Begin Cayenne

  Console.println("Connected!");
  timer = millis();
  extraTime = millis();

  //Set each digital pin as input or output
  pinMode(RED, OUTPUT);
  pinMode(GREEN, OUTPUT);
  pinMode(BLUE, OUTPUT);
  pinMode(pirPin, INPUT);

  pinMode(piezoPin, OUTPUT);
  pinMode(irDistPlus, OUTPUT);

  //Initial "on and off" to show everything is working
  analogWrite(RED, bright);
  analogWrite(GREEN, bright);
  analogWrite(BLUE, bright);
  delay(2000);
  analogWrite(GREEN, 0);
  analogWrite(BLUE, 0);
  analogWrite(RED, 0);

}

void loop() {
  Cayenne.run();


  pirVal = PIR();       //Check the current state of the PIR

  
  PhotoCell(pirVal);    //Check if light needs to be turned on or off

  

}


// Check the PIR value -- uncomment to see the value in the monitor
int PIR() {
  pirVal = digitalRead(pirPin);
  // Console.print("PIR is ");
  // Console.println(pirVal);
  return pirVal;
}

// Check value of light, and determine if LED should be on or off
void PhotoCell(int pir) {
  int redBright, greenBright, blueBright;
  photoReading = analogRead(photoPin);      // Check light value
  ReceiveLightValue();                      // Receive temp range from ESP8266
  
  // If light is dim, there is movement, and LEDs are not already on, turn it on
  if((photoReading <= threshold) && (pir == HIGH) && !isOn) {
    isOn = true;
    timer = millis();
    //Console.println("Turn on");
    Sim();                                  // do a simulation and produce a random color
    RandColor(&redBright, &greenBright, &blueBright);
    delay(1000);
  }
  
  if(isOn) {      // In the first phase, do nothing -- just leave the light on for timeLim seconds

    if (millis() - timer > timeLim) {     // We must now enter the second phase

      pir = 0;
      nextmode = 1;
      
      extraTime = millis();
      timer = millis();
    }
    if (nextmode) {                   // Add all the values of the PIR during the second phase
      pirNum = PIR() + pirNum;        
      //Console.print("pirNum = ");
      //Console.println(pirNum);
    }

    if((nextmode) && (millis() - extraTime > extraTimeLim)) {
      Console.println("Checking if needs to be on.");
      if (pirNum <= PIRNUM) {     // If the number of movements is less than PIRNUM (default 1)
                                  // turn off; otherwise stay on
        isOn = false;
        nextmode = 0;
        Console.println("Turn off");
        digitalWrite(piezoPin, HIGH);     // buzzer signals that light will turn off
        delay(300);
        digitalWrite(piezoPin, LOW);
        delay(1000);
        analogWrite(RED, 0);
        analogWrite(GREEN, 0);
        analogWrite(BLUE, 0);
        delay(10);
      }
      extraTime = millis();     // reset all timers
      timer = millis();
      pirNum = 0;
    }
    
  }
  

  
  delay(500);
}

// Receive temperature range code from Linux side of Yn (using Bridge)
void ReceiveLightValue() {
  int Dint = 0;
  Bridge.begin();
  Bridge.get("D3", Dvalue, 2);
  Dint = atoi(Dvalue);
  int weatherTime = 10000;
  Console.println(Dint);
  switch (Dint) {
    case 0:
      //do nothing
      break;
    case 1:
      //Pink
      isOn = true;
      timer = millis();
      analogWrite(RED, 255);
      analogWrite(GREEN, 180);
      analogWrite(BLUE, 255);
      delay(weatherTime);
      break;
    case 2:
      //Red
      isOn = true;
      timer = millis();      
      analogWrite(RED, 255);
      analogWrite(GREEN, 0);
      analogWrite(BLUE, 0);
      delay(weatherTime);
      break;
    case 3:
      //Orange
      isOn = true;
      timer = millis();      
      analogWrite(RED, 255);
      analogWrite(GREEN, 80);
      analogWrite(BLUE, 0);
      delay(weatherTime);
      break;
    case 4:
      //Yellow
      isOn = true;
      timer = millis();      
      analogWrite(RED, 230);
      analogWrite(GREEN, 255);
      analogWrite(BLUE, 0);
      delay(weatherTime);
      break;
    case 5:
      //Green
      isOn = true;
      timer = millis();      
      analogWrite(RED, 0);
      analogWrite(GREEN, 255);
      analogWrite(BLUE, 0);
      delay(weatherTime);
      break;
    case 6:
      //Blue
      isOn = true;
      timer = millis();      
      analogWrite(RED, 0);
      analogWrite(GREEN, 0);
      analogWrite(BLUE, 255);
      delay(weatherTime);
      break;
    case 7:
      //Purple
      isOn = true;
      timer = millis();      
      analogWrite(RED, 225);
      analogWrite(GREEN, 0);
      analogWrite(BLUE, 255);
      delay(weatherTime);
      break; 
    case 8:
      //White
      isOn = true;
      timer = millis();
      analogWrite(RED, 255);
      analogWrite(GREEN, 255);
      analogWrite(BLUE, 255);
      delay(weatherTime);
      break;       
  }
  
}

// Run a simulation: first fade to red, then fade to yellow, then fade to white
void Sim() {
  int r, g, b;
  analogWrite(GREEN, 0);
  analogWrite(BLUE, 0);
  analogWrite(RED, 0);
  delay(200);
  for(r = 0; r < 255; r++) {
    analogWrite(RED, r);
    delay(5);
  }
  for(g = 0; g < 255; g++) {
    analogWrite(GREEN, g);
    delay(5);
  }
  for(b = 0; b < 255; b++) {
    analogWrite(BLUE, b);
    delay(5);
  }

  delay(500);  
}

// Produce a random color that is dim (between 1 and 25 out of 255)
void RandColor(int *redBright, int *greenBright, int *blueBright) {
  int randR = 0;
  int randG = 0;
  int randB = 0;
  int x, y, z;

  randomSeed(analogRead(1));
    
  randR = random(1, 25);
  randG = random(1, 25);
  randB = random(1, 25);

  
  for(int i = 100; i > 0; i--) {  //Fade backwards from white to random color in 100 intervals
    x = i;
    y = i;
    z = i;

    *redBright = map(x, 1, 100, randR, 255); 
    *greenBright = map(y, 1, 100, randG, 255); 
    *blueBright = map(z, 1, 100, randB, 255); 

    analogWrite(RED, *redBright);
    analogWrite(GREEN, *greenBright);
    analogWrite(BLUE, *blueBright);
    delay(50);
  }


}



// The following code has been auto-generated by Cayenne for its sliders to control the LED Strip
CAYENNE_IN(REDVP)
{
  // get value sent from dashboard
  int currentValue = getValue.asInt(); // 0 to 255
  analogWrite(RED, currentValue); // analogWrite accepts a value from 0 to 255
}

CAYENNE_IN(GREENVP)
{
  // get value sent from dashboard
  int currentValue = getValue.asInt(); // 0 to 255
  analogWrite(GREEN, currentValue); // analogWrite accepts a value from 0 to 255
}

CAYENNE_IN(BLUEVP)
{
  // get value sent from dashboard
  int currentValue = getValue.asInt(); // 0 to 255
  analogWrite(BLUE, currentValue); // analogWrite accepts a value from 0 to 255
}

ESP8266 Code

Arduino
The Remote Control Module has some photocells, an IR Transmitter / Receiver pair, and an RGB LED. It senses motion in a remote location (e.g. hallway), indicates the outside temperature with the color of the RGB LED, and if it's dark, sends a code to the Arduino Yun's AR9331 processor via Wi-Fi. This compact module can be used to monitor the motion of a baby or pet.
/* This is the ESP8266 code for the Smart Ambient Lighting Project
 *  Uses Weather Underground API
 *  
 *  Uses code from the following website: https://gist.github.com/bbx10/149bba466b1e2cd887bf
 *  for utilizing the Weather Underground API.
 *  
 *  Instructions for establishing TCP connection to Yn:
 *  https://github.com/iot-playground/Arduino/blob/master/ESP8266ArduinoIDE/WiFiWebServer/WiFiWebServer.ino
 *  
 *  The ESP8266 board is connected to photocells, an IR Transmitter/Receiver, and
 *  an RGB LED. When motion is detected, the LED lights up according to the outside 
 *  temperature. If it is locally dark, the ESP sends a signal to Arduino Yn's
 *  Python program to turn on the Family Room Lights.
 *  
 * Created by Daniel Martin
 */

// To setup the board, follow these instructions:
// https://learn.sparkfun.com/tutorials/esp8266-thing-development-board-hookup-guide/all

// Go to https://www.wunderground.com/weather/api to create a free account and select a plan

// Install libraries:
// https://github.com/adafruit/Adafruit_NeoPixel
// https://github.com/myDevicesIoT/Cayenne-MQTT-ESP8266

#include <ESP8266WiFi.h>
#include <LiquidCrystal.h>
#include <Wire.h>
#include <Adafruit_NeoPixel.h>
#include <ArduinoJson.h>

#define CAYENNE_PRINT Serial
#include <CayenneMQTTESP8266.h>

#define WU_API_KEY "*************"  // From Weather Underground website

#define WU_LOCATION "90001"         // Change this to your zip code

int outTemp = 72;     // initial temperature (a placeholder until the real value is received)
long timer = millis();

long interval = 5*60*1000;   // 5 minute delay

#define DELAY_NORMAL    (5*60*1000)

#define DELAY_ERROR     (20*60*1000)

#define WUNDERGROUND "api.wunderground.com"

// HTTP request
const char WUNDERGROUND_REQ[] =
    "GET /api/" WU_API_KEY "/conditions/q/" WU_LOCATION ".json HTTP/1.1\r\n"
    "User-Agent: ESP8266/0.1\r\n"
    "Accept: */*\r\n"
    "Host: " WUNDERGROUND "\r\n"
    "Connection: close\r\n"
    "\r\n";
static char respBuf[4096];

int irRec = 12;               // IR Receiver digital pin number
int irLed = 13;               // IR Transmitter digital pin number
int maxNumIR = 5;             // Number of 1's received to trigger LED
int led = 14;                 // RGB LED pin
int photoPin = A0;            // ADC pin for photocells
bool irTrue = false;
unsigned long lastMillis = 0;

// Setup of RGB LED
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(1, led, NEO_RGB + NEO_KHZ400);


char s = ' ';
const char* host = "100.100.1.10";        // Change to your IP Address
char ssid[] = "*********";                // Change to your SSID
char wifiPassword[] = "***********";      // Change to your Wi-Fi password


// Go to cayenne.mydevices.com to setup your Sparkfun board
char username[] = "****-***-***-***-******";    // Username from Cayenne
char password[] = "****************";           // Password from Cayenne
char clientID[] = "******-***-***-***-********"; // Client ID from Cayenne

WiFiClient client;

void setup() {
  pinMode(irRec, INPUT);  pinMode(irLed, OUTPUT);   // IR LED & Receiver
  Serial.begin(9600);
  delay(10);
  Cayenne.begin(username, password, clientID, ssid, wifiPassword);
  pixels.begin();
  pixels.setPixelColor(0, pixels.Color(0, 0, 0));
  pixels.show();

  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

   delay(5000);

  Serial.print("connecting to ");
  Serial.println(host);

  // Use WiFiClient class to create TCP connections
  // We are using port 5560 -- must be consist with Yn's python code
  const int port = 5560;        
  if (!client.connect(host, port)) 
  {
    Serial.println("connection failed");
    return;
  }

}

void loop() {
  Cayenne.loop();
  int photoval = analogRead(photoPin);          // Read the value of light intensity
  Serial.println(photoval);
  
  irTrue = IRSensor();                        // Check if there is motion
  
  if((irTrue) && (photoval >= 600)) {        // If there is enough light, only turn on LED
    OutTempRead();
  }
  else if ((irTrue) && (photoval < 600)) {   // If not enough light, send to Yun also

    OutTempRead();
    sendToYun();

    delay(1000);
  }

  if (millis() - lastMillis > 10000) {
    lastMillis = millis();

    Cayenne.fahrenheitWrite(1, outTemp);
    
    Cayenne.virtualWrite(2, photoval);
    Cayenne.virtualWrite(3, irTrue);

  }


  if(millis() - timer > interval) {     // Every 5 mins, check temperature
    WunderSetup();
    timer = millis();
  }
  delay(2000);

}

// Send a different number to Yn based on the outside temperature
void sendToYun() {
  Serial.println("Sending to Yun.");
  if (outTemp > 100) {
    client.print('8');
    delay(1000); 
    client.print('0');
  }
  else if (outTemp > 90) {
    client.print('1'); 
    delay(1000); 
    client.print('0');
  }
  else if (outTemp > 80) {
    client.print('2'); 
    delay(1000); 
    client.print('0');    
  }
  else if (outTemp > 70) {
    client.print('3');
    delay(1000); 
    client.print('0');     
  }
  else if (outTemp > 60) {
    client.print('4'); 
    delay(1000); 
    client.print('0');    
  }
  else if (outTemp > 50) {
    client.print('5'); 
    delay(1000); 
    client.print('0');    
  }
  else if (outTemp > 40) {
    client.print('6');
    delay(1000); 
    client.print('0');     
  }
  else if (outTemp <= 40) {
    client.print('7'); 
    delay(1000); 
    client.print('0');    
  }
}


int OutTempRead() {       // Set the RGB LED based on the outside temp

  if (outTemp < 60) {
    pixels.setPixelColor(0, pixels.Color(0, 0, 0));
    pixels.show();
    delay(100);
    pixels.setPixelColor(0, pixels.Color(0, 255, 0));
    pixels.show();
    delay(4000);
    pixels.setPixelColor(0, pixels.Color(0, 0, 0));
    pixels.show();
    pixels.setPixelColor(0, pixels.Color(0, 0, 0));
    pixels.show();
    delay(1000);
  }
  else if(outTemp >= 60 && outTemp <= 80) {
    pixels.setPixelColor(0, pixels.Color(0, 0, 0));
    pixels.show();
    delay(100);
    pixels.setPixelColor(0, pixels.Color(255, 0, 0));
    pixels.show();
    delay(4000);
    pixels.setPixelColor(0, pixels.Color(0, 0, 0));
    pixels.show();
    pixels.setPixelColor(0, pixels.Color(0, 0, 0));
    pixels.show();
    delay(1000);   
  }
  else {
    pixels.setPixelColor(0, pixels.Color(255, 255, 255));
    pixels.show();
    pixels.setPixelColor(0, pixels.Color(0, 0, 0));
    pixels.show();
    delay(4000);
    pixels.setPixelColor(0, pixels.Color(0, 0, 0));
    pixels.show();
    pixels.setPixelColor(0, pixels.Color(0, 0, 0));
    pixels.show();
    delay(1000);   
  }
}

// Connect to Weather Underground -- modified from the website mentioned above
void WunderSetup() {
 // TODO check for disconnect from AP

  // Open socket to WU server port 80
  Serial.print(F("Connecting to "));
  Serial.println(WUNDERGROUND);

  // Use WiFiClient class to create TCP connections
  WiFiClient httpclient;
  const int httpPort = 80;
  if (!httpclient.connect(WUNDERGROUND, httpPort)) {
    Serial.println(F("connection failed"));
    delay(DELAY_ERROR);
    return;
  }

  // This will send the http request to the server
  Serial.print(WUNDERGROUND_REQ);
  httpclient.print(WUNDERGROUND_REQ);
  httpclient.flush();

  // Collect http response headers and content from Weather Underground
  // HTTP headers are discarded.
  // The content is formatted in JSON and is left in respBuf.
  int respLen = 0;
  bool skip_headers = true;
  while (httpclient.connected() || httpclient.available()) {
    if (skip_headers) {
      String aLine = httpclient.readStringUntil('\n');
      //Serial.println(aLine);
      // Blank line denotes end of headers
      if (aLine.length() <= 1) {
        skip_headers = false;
      }
    }
    else {
      int bytesIn;
      bytesIn = httpclient.read((uint8_t *)&respBuf[respLen], sizeof(respBuf) - respLen);
      Serial.print(F("bytesIn ")); Serial.println(bytesIn);
      if (bytesIn > 0) {
        respLen += bytesIn;
        if (respLen > sizeof(respBuf)) respLen = sizeof(respBuf);
      }
      else if (bytesIn < 0) {
        Serial.print(F("read error "));
        Serial.println(bytesIn);
      }
    }
    delay(1);
  }
  httpclient.stop();

  if (respLen >= sizeof(respBuf)) {
    Serial.print(F("respBuf overflow "));
    Serial.println(respLen);
    delay(DELAY_ERROR);
    return;
  }
  // Terminate the C string
  respBuf[respLen++] = '\0';


  showWeather(respBuf);

}

// Find out the current temperature -- modified from the website mentioned above
void showWeather(char *json)
{
  StaticJsonBuffer<3*1024> jsonBuffer;

  // Skip characters until first '{' found
  // Ignore chunked length, if present
  char *jsonstart = strchr(json, '{');
  //Serial.print(F("jsonstart ")); Serial.println(jsonstart);
  if (jsonstart == NULL) {
    Serial.println(F("JSON data missing"));
    //return false;
  }
  json = jsonstart;

  // Parse JSON
  JsonObject& root = jsonBuffer.parseObject(json);
  if (!root.success()) {
    Serial.println(F("jsonBuffer.parseObject() failed"));
    //return false;
  }

  // Extract weather info from parsed JSON
  JsonObject& current = root["current_observation"];
  const float temp_f = current["temp_f"];
  outTemp = round(temp_f);
  Serial.print(outTemp); Serial.print(F(" F"));

}

// Check if there is motion
bool IRSensor() {
  int irvals = 0;
  for (int i = 0; i < 20; i++) {      // Check 20 times to account for random detection
    irvals = irvals + irDetect(irLed, irRec, 38000);       // Check for object
    //delay(15);
  }
  Serial.println(irvals);                    

  if(irvals > maxNumIR) {     // If 5/20 are 1's, then we know for sure there is motion
    return true;
  }
  else {
    pixels.setPixelColor(0, pixels.Color(0, 0, 0));
    pixels.show();
    return false;
  }
  
  

}

// Send and receive an IR signal
int irDetect(int irLedPin, int irReceiverPin, long frequency)
{
  tone(irLedPin, frequency, 8);              // IRLED 38 kHz for at least 1 ms
  delay(1);                                  // Wait 1 ms
  int ir = digitalRead(irReceiverPin);       // IR receiver -> ir variable
  delay(1);                                  // Down time before recheck
  return !(ir);                                 // Return 1 no detect, 0 detect
}  

//The following function is taken from Cayenne
//Default function for processing actuator commands from the Cayenne Dashboard.
//You can also use functions for specific channels, e.g CAYENNE_IN(1) for channel 1 commands.
CAYENNE_IN_DEFAULT()
{
  CAYENNE_LOG("CAYENNE_IN_DEFAULT(%u) - %s, %s", request.channel, getValue.getId(), getValue.asString());
  //Process message here. If there is an error set an error message using getValue.setError(), e.g getValue.setError("Error message");
}

Arduino Yun's AR9331 Code

Python
The AR9331 processor receives a code via Wi-Fi from the ESP8266 and passes it on to the 32U4 processor via the Bridge.
# This is the Python code for the Smart Ambient Lighting Project
# Runs on Linux side of Arduino Yún

# Using TCP communication to the ESP8266, this program receives 
# a value based on the outside temperature and sends it to the 
# Arduino side of the board through Bridge

# Modified by Daniel Martin
# Majority of this code was created by Alexander Baran-Harper
# using this tutorial: https://www.youtube.com/watch?v=PYBZtV2-sLQ



import socket
import time

import sys
sys.path.insert(0, '/usr/lib/python2.7/bridge')

from bridgeclient import BridgeClient as bridgeclient
value = bridgeclient()

host = ''
port = 5560



def setupServer():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print("Socket created.")
    try:
        s.bind((host, port))
    except socket.error as msg:
        print(msg)
    print("Socket bind complete.")
    return s

def setupConnection():
    s.listen(1) # Allows one connection at a time.
    conn, address = s.accept()
    print("Connected to: " + address[0] + ":" + str(address[1]))
    return conn



def dataTransfer(conn):
    # A big loop that sends/receives data until told not to.
    while True:
        # Receive the data
        time.sleep(1)
        data = conn.recv(20) # receive the data
        data = data.decode('utf-8')
        # Split the data such that you separate the command
        # from the rest of the data.
        dataMessage = data.split(' ', 1)
        command = dataMessage[0]

        print(command)
        value.put('D3', command)

    conn.close()
        

s = setupServer()

while True:
    try:
        conn = setupConnection()
        dataTransfer(conn)
    except:
        break

Credits

Daniel Martin

Daniel Martin

0 projects • 4 followers
I am studying EE in UC Davis, and interested in tinkering with Arduino and Pi. Some of my Maker projects are at piduino.weebly.com
Thanks to Weather Underground, Alexander Baran-Harper , Adafruit, Sparkfun, and Cayenne.

Comments