fab-lab.eu
Created January 10, 2016

Where is my elevator? (Ist mein Aufzug schon da?)

This project was created during the #DBhackathon, using open & sensor data to improve / innovate the service of public transportation (rail)

IntermediateWork in progress660
Where is my elevator? (Ist mein Aufzug schon da?)

Things used in this project

Story

Read more

Code

Die Anwendungslogik auf Basis von Arduino und ESP8266

Arduino
zeigt jetzt auch auf einem OLED Status und Daten an, Daten werden an data.sparkfun.com/aufzug gesendet, Trigger an IFTTT via Maker Channel, Regeln für Stockwerkserkennung prototypisch - wir gehen davon aus dass diese Daten später aus der Aufzugsteuerung übernommen werden können, oder sonst hier die Logik entsprechen erweitert wird - funktioniert prima ...
# written by Guido Burger code as it is, prototyp during #dbhackathon
# www-fab-lab.eu

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>
// Include the ESP8266 WiFi library. (Works a lot like the
// Arduino WiFi library.)
#include <ESP8266WiFi.h>
// Include the SparkFun Phant library.
#include <Phant.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 14
Adafruit_SSD1306 display(OLED_RESET);
#define LOGO16_GLCD_HEIGHT 16 
#define LOGO16_GLCD_WIDTH  16 

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

Adafruit_BMP085 bmp;

const char WiFiSSID[] = "YOURSSID";
const char WiFiPSK[] =  "YOURKEY";

const int LED_PIN = 0; // Thing's onboard, green LED
const int ANALOG_PIN = A0; // The only analog pin on the Thing
const int DIGITAL_PIN = 12; // Digital pin to be read

const char PhantHost[] = "data.sparkfun.com";
const char PublicKey[] = "YOURPUBLICKEY";
const char PrivateKey[] = "YOURPRIVATEKEY";

const unsigned long postRate = 2000; //2000;
unsigned long lastPost = 0;

StaticJsonBuffer<600> jsonBuffer;
uint8_t buff[600] = { 0 };
//char post_data[200];

long EG_level = 0;

void connectWiFi()
{
  byte ledStatus = LOW;

  // Set WiFi mode to station (as opposed to AP or AP_STA)
  WiFi.mode(WIFI_STA);

  // WiFI.begin([ssid], [passkey]) initiates a WiFI connection
  // to the stated [ssid], using the [passkey] as a WPA, WPA2,
  // or WEP passphrase.
  WiFi.begin(WiFiSSID, WiFiPSK);

  // Use the WiFi.status() function to check if the ESP8266
  // is connected to a WiFi network.
  while (WiFi.status() != WL_CONNECTED)
  {
    // Blink the LED
    digitalWrite(LED_PIN, ledStatus); // Write LED high/low
    ledStatus = (ledStatus == HIGH) ? LOW : HIGH;

    // Delays allow the ESP8266 to perform critical tasks
    // defined outside of the sketch. These tasks include
    // setting up, and maintaining, a WiFi connection.
    delay(100);
    // Potentially infinite loops are generally dangerous.
    // Add delays -- allowing the processor to perform other
    // tasks -- wherever possible.
  }
}

void initHardware()
{
  Serial.begin(9600);
  pinMode(DIGITAL_PIN, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  // Don't need to set ANALOG_PIN as input, 
  // that's all it can be.
}

//JSON return example as of api.aufzugswaechter.org
//{"type":"feature","properties":{"stationnumber":5276,"stationname":"Riesa","facilityEquipmentnumber":10054040,"facilityType":"ELEVATOR","facilityDescription":"Aufzug zu Bstg 2/3","facilityState":"ACTIVE","facilityStateKnownSince":1452188310597},"geometry":{"type":"Point","coordinates":[13.287900814000000337955498252995312213897705078125,51.3097138899999976047183736227452754974365234375]}}

String initStation(String id) //10054040
{
  // DB API data
  const char* id_1 = "NA";
  const char* desc_1 = "NA";
  const char* state_1 = "NA";

  HTTPClient http;
  http.begin("api.aufzugswaechter.org", 80, "/facilities/"+id); //HTTP, facility number based lookup via DB API (aufzugswaechter.org)
  int httpCode = http.GET();
        if(httpCode) {
            // HTTP header has been send and Server response header has been handled

            Serial.printf("[HTTP] GET... code: %d\n", httpCode);

            // file found at server
            if(httpCode == 200) {

                // get lenght of document (is -1 when Server sends no Content-Length header)
                int len = http.getSize();

                // create buffer for read
//                uint8_t buff[600] = { 0 };

                // get tcp stream
                WiFiClient * stream = http.getStreamPtr();

                // read all data from server
                while(http.connected() && (len > 0 || len == -1)) {
                    // get available data size
                    size_t size = stream->available();

                    if(size) {
                        // read up to 600 byte
                        int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));

                        // write it to Serial
                        //Serial.write(buff, c); 

                        // convert buffer to string
                        char string_received[600] = "";
                        for (int m=0; m<sizeof(buff); m++)
                        {
                          string_received[m] = char(buff[m]);
                        }
                        Serial.println(string_received);
                        JsonObject& root = jsonBuffer.parseObject(string_received);

                        id_1 = root["properties"]["facilityEquipmentnumber"];
                        desc_1 = root["properties"]["facilityDescription"];
                        state_1 = root["properties"]["facilityState"];
                        //double latitude = root["data"][0];
                        //double longitude = root["data"][1];

                        Serial.println(id_1);
                        Serial.println(desc_1);
                        Serial.println(state_1);
                        //Serial.println(latitude, 6);
                        //Serial.println(longitude, 6);

                         if(len > 0) {
                            len -= c;
                        }
                    }
                    delay(1);
                }
                Serial.println();
                Serial.print("[HTTP] connection closed or file end.\n");
            }
        } else {
            Serial.print("[HTTP] GET... failed, no connection or no HTTP server\n");
        }
        return desc_1; // return where is elevator with given id located
}

int postToPhant()
{  
    String floor_level;
    String service_level;
  
    Serial.print("Temperature = ");
    Serial.print(bmp.readTemperature());
    Serial.println(" *C");
    
    Serial.print("Pressure = ");
    Serial.print(bmp.readPressure());
    Serial.println(" Pa");
    
    // Calculate altitude assuming 'standard' barometric
    // pressure of 1013.25 millibar = 101325 Pascal
    Serial.print("Altitude = ");
    Serial.print(bmp.readAltitude());
    Serial.println(" meters");

    Serial.print("Pressure at sealevel (calculated) = ");
    Serial.print(bmp.readSealevelPressure());
    Serial.println(" Pa");

  // you can get a more precise measurement of altitude
  // if you know the current sea level pressure which will
  // vary with weather and such. If it is 1015 millibars
  // that is equal to 101500 Pascals.
    Serial.print("Real altitude = ");
    Serial.print(bmp.readAltitude(101500));
    Serial.println(" meters");
    Serial.println();
    delay(500);

 // Clear the buffer.
  display.clearDisplay();
  // text display tests
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("#DBhackathon");
  display.println("Aufzug-ID: 10054040");
  display.setTextSize(1);
  display.print("Temp: ");
  display.print(bmp.readTemperature());
  display.print("C VOC: ");
  display.println(analogRead(ANALOG_PIN));

  // if beacon close by
  // check beacon 
  int binda = digitalRead(DIGITAL_PIN);

  // Declare an object from the Phant library - phant
  Phant phant(PhantHost, PublicKey, PrivateKey);

  // Do a little work to get a unique-ish name. Append the
  // last two bytes of the MAC (HEX'd) to "Thing-":
  uint8_t mac[WL_MAC_ADDR_LENGTH];
  WiFi.macAddress(mac);
  String macID = String(mac[WL_MAC_ADDR_LENGTH - 2], HEX) +
                 String(mac[WL_MAC_ADDR_LENGTH - 1], HEX);
  macID.toUpperCase();
  String postedID = "Thing-" + macID;

  // Add the four field/value pairs defined by our stream:
  
  phant.add("air", analogRead(ANALOG_PIN)); // air quality
  phant.add("count", 8); // number people 
  phant.add("door", binda); // beacon proximity
  //phant.add("id", postedID);
  phant.add("id", 101500); // elevator staion id
  phant.add("level", bmp.readAltitude(101500)); // floor level
  phant.add("temp", String(bmp.readTemperature())); // environment temp
  
  //phant.add("time", millis()); // local timer

  // Now connect to data.sparkfun.com, and post our data:
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(PhantHost, httpPort)) 
  {
    // If we fail to connect, return 0.
    return 0;
  }
  // If we successfully connected, print our Phant post:
  client.print(phant.post());

  // Read all the lines of the reply from server and print them to Serial
  while(client.available()){
    String line = client.readStringUntil('\r');
    //Serial.print(line); // Trying to avoid using serial
  }


  // range of value mapped to floor_level, need to be calibrated once, auto-calibration possible due to min/max
  if (bmp.readAltitude(101500)>=(EG_level-1) && bmp.readAltitude(101500)<(EG_level+1)) {
    floor_level = "EG";
  }
  else
  {
    floor_level = "--";
  }

 
  display.print("Level: ");
  display.print(floor_level);

  // not working yet
  if (WiFi.status() == WL_CONNECTED) {
  display.println("   Wifi: on");  
  }
  else
  {
    display.println("  Wifi: off");
  }
  
  // fresh air based on the air quality (VOC) sensor rates the service_level, many people or bad service 
  // value < 80 equals "fresh air"
  if (analogRead(ANALOG_PIN)<80) {
    service_level = "****";
  }
  else
  {
    service_level = "*";
  }

    // LED turns on when we enter, it'll go off when we 
    // successfully post
    digitalWrite(LED_PIN, HIGH);

  // Before we exit, turn the LED off.
  delay(500);
  digitalWrite(LED_PIN, LOW);
 
  if (binda ==  1){
    String post_data = "/trigger/aufzug/with/key/<YOURKEY>?value1="+initStation("10054040");
    post_data = post_data+"&value2="+floor_level+" "+service_level;
    post_data = post_data+"&value3="+String(bmp.readTemperature());

    Serial.println(post_data);

    HTTPClient http;
    http.begin("maker.ifttt.com", 80, post_data); //HTTP
    int httpCode = http.GET();
    Serial.print("HTTP GET ... code:");
    Serial.println(httpCode);   
  }

   display.display();
  delay(2000);
  
  return 1; // Return success
}

void setup() 
{
  delay(4000);

    // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
  // init done

  // Show image buffer on the display hardware.
  // Since the buffer is intialized with an Adafruit splashscreen
  // internally, this will display the splashscreen.
  display.display();
  delay(500);
   // Clear the buffer.
  display.clearDisplay();
  
  Serial.begin(9600);
  if (!bmp.begin()) {
  Serial.println("Could not find a valid BMP085 sensor, check wiring!");
  while (1) {}
  }
  
  initHardware();
  connectWiFi();
  digitalWrite(LED_PIN, HIGH);

  EG_level = bmp.readAltitude(101500);
  Serial.print("EG level auf: "); 
  Serial.println(EG_level);
}

void loop() 
{
  if (lastPost + postRate <= millis())
  {
    if (postToPhant())
      lastPost = millis();
    else
      delay(100);    
  }
}

Credits

fab-lab.eu

fab-lab.eu

22 projects • 276 followers
Maker!

Comments