Introduction: EAL-Industry 4.0-Drinkster_2.0

( All is written in Danish )

Indledning

I denne præsentation vil vi
vise og beskrive, hvordan vi har fået implementeret industri 4.0 ind i et tidligere projekt ”Drinks Anlæg”. Så vi med vores smartphone eller computer kan bestille en drink på vores anlæg. (link kommer længere nede)

Industri 4.0 er integrationen mellem den digitale verden og den fysiske produktion. Så vi på den måde får gjort vores produktion mere intelligent. Der kan ligeledes kommunikeres på kryds af landegrænser, så selvom en person sidder i fx Danmark kan der sagtens ændres på en produktion i Spanien eller et andet land.

F.eks. Når en familie Danmark sidder hjemme i deres stue og bestiller deres fabriks nye bil fra VW. Farve, gearkasse, lygter, anlæg, etc. Så ved den intelligente produktion nede i Tyskland det, med det samme. Der skal derfor ikke en medarbejder ind og fortælle samleanlægget det. Ligeledes hvis der mangler en bestemt del, så bliver det bestilt fra leverandøren med det samme, de bestiller deres nye bil.

Punkter vi kommer igennem:

1 - Link til anlægget.

2 - Flowchart

3 - Opsætning af Raspberry, database, Node-red samt PHPmyadmin.

4 - Arduino opgradering

5 - Visual studio - Windows form

Step 1: Link Til Drinks Anlæg

Vi har valgt at arbejde videre på vores tidligere projekt, for at optimerer og udvikle mere, i takt med vi har lært mere i vores undervisning. Herunder findes link til tidligere anlæg, som beskriver byggeprocessen step by step, med tilhørende filer til download.

LINKS:

Drinks Anlæg

https://www.instructables.com/id/EAL-Drinks-Anl%C3...

Step 2: Flowchart

Flowchart

Der er udarbejdet et flow/sekvens diagram over selve anlægget. Dette er med til at give et overblik over processen og hvordan den virker for forbrugeren. Det er også med til at vise hvordan programmet bliver afviklet, og på hvilken måde.

Step 3: Opsætning Af Raspberry, Database, Node-red Og Phpmyadmin.

Først opdateres Raspberry Pie og ændringer installeres

· sudo apt-get update

· sudo apt-get upgrade

· sudo apt-get install npm

Herefter installeres node-red og de forskellige tilføjelses pakker

· cd ~/.node-red

· npm install node-red-dashboard

· npm install node-red

· npm install node-red-node-mysql

· npm install node-red-node-arduino

Apache2 installeres for at vi kan sidde direkte på Raspberry Pie og ændre i databasen via phpmyadmin

· sudo apt install apache2

· sudo chown –R pi:www-data /var/www/html/

· sudo chmod –R 770 /var/www/html/

PHP, mysql-server, phpmyadmin installeres for at vi kan benytte vores database

· sudo apt install php

· sudo apt install mysql-server php-mysql

· sudo aptitude install phpmyadmin

”This will start installing the packages. You will be asked which Web Server is to be used. Choose apache2.”

(Se billede 1 i toppen)

”Next, we will need to configure the database phpmyAdmin should use. For that you should select Yes when asked:”

(Se billede 2 i toppen)

indtast adgangskode som du også vil bruge til mysql senere, husk den derfor til senere step.

Der skal ændres lidt apache2.conf filen for at tingene virker

· sudo nano /etc/apache2/apache2.conf

· ctrl+v helt til bunden og skriv følgende:

· Include /etc/phpmyadmin/apache.conf

· ctrl+x og enter efterfølgende

· sudo /etc/init.d/apache2 restart

Af en eller anden grund er der behov for at flush privileges i mysql databesen

· sudo mysql –u root

· use mysql;

· update user set plugin=’’ where user=’root’;

· flush privileges;

· exit;

opret adgangskode til mysql database:

· sudo mysql_secure_installation

Nu burde du kunne logge ind på 127.0.0.1/phpmyadmin

Bruger root og adgangskode som du har lavet.

Step 4: Arduino

Da vi har opgraderet vores drinkster til en version 2.0, har vi været inde og ændre i vores tidligere koden, for at få dette til at virke efter hensigten. For at kunne oprette forbindelse imellem Raspberry pi og arduino, har vi tilføjet en programdel som gør dette muligt. Disse Findes herunder. Hele koden for anlægget findes i bunden. ( der er linket i koden, hvor denne kan findes)

Herunder findes den nye del af koden som er blevet lavet. Denne program del er lavet ud i

<p>/*<br>  Firmata is a generic protocol for communicating with microcontrollers
  from software on a host computer. It is intended to work with
  any host computer software package.
  To download a host software package, please click on the following link
  to open the list of Firmata client libraries in your default browser.
  <a href="https://github.com/firmata/arduino#firmata-client-libraries" rel="nofollow"> https://github.com/firmata/arduino#firmata-client...</a>
  Copyright (C) 2006-2008 Hans-Christoph Steiner.  All rights reserved.
  Copyright (C) 2010-2011 Paul Stoffregen.  All rights reserved.
  Copyright (C) 2009 Shigeru Kobayashi.  All rights reserved.
  Copyright (C) 2009-2016 Jeff Hoefs.  All rights reserved.
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  See file LICENSE.txt for further informations on licensing terms.
  Last updated October 16th, 2016
*/
#include 
#include 
#include 
#define I2C_WRITE                   B00000000
#define I2C_READ                    B00001000
#define I2C_READ_CONTINUOUSLY       B00010000
#define I2C_STOP_READING            B00011000
#define I2C_READ_WRITE_MODE_MASK    B00011000
#define I2C_10BIT_ADDRESS_MODE_MASK B00100000
#define I2C_END_TX_MASK             B01000000
#define I2C_STOP_TX                 1
#define I2C_RESTART_TX              0
#define I2C_MAX_QUERIES             8
#define I2C_REGISTER_NOT_SPECIFIED  -1
// the minimum interval for sampling analog input
#define MINIMUM_SAMPLING_INTERVAL   1</p><p>/*==============================================================================
 * GLOBAL VARIABLES
 *============================================================================*/
#ifdef FIRMATA_SERIAL_FEATURE
SerialFirmata serialFeature;
#endif
/* analog inputs */
int analogInputsToReport = 0; // bitwise array to store pin reporting
/* digital input ports */
byte reportPINs[TOTAL_PORTS];       // 1 = report this port, 0 = silence
byte previousPINs[TOTAL_PORTS];     // previous 8 bits sent
/* pins configuration */
byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else
/* timer variables */
unsigned long currentMillis;        // store the current value from millis()
unsigned long previousMillis;       // for comparison with currentMillis
unsigned int samplingInterval = 19; // how often to run the main loop (in ms)
/* i2c data */
struct i2c_device_info {
  byte addr;
  int reg;
  byte bytes;
  byte stopTX;
};
/* for i2c read continuous more */
i2c_device_info query[I2C_MAX_QUERIES];
byte i2cRxData[64];
boolean isI2CEnabled = false;
signed char queryIndex = -1;
// default delay time between i2c read request and Wire.requestFrom()
unsigned int i2cReadDelayTime = 0;
Servo servos[MAX_SERVOS];
byte servoPinMap[TOTAL_PINS];
byte detachedServos[MAX_SERVOS];
byte detachedServoCount = 0;
byte servoCount = 0;
boolean isResetting = false;
// Forward declare a few functions to avoid compiler errors with older versions
// of the Arduino IDE.
void setPinModeCallback(byte, int);
void reportAnalogCallback(byte analogPin, int value);
void sysexCallback(byte, byte, byte*);
/* utility functions */
void wireWrite(byte data)
{
#if ARDUINO >= 100
  Wire.write((byte)data);
#else
  Wire.send(data);
#endif
}
byte wireRead(void)
{
#if ARDUINO >= 100
  return Wire.read();
#else
  return Wire.receive();
#endif
}
/*==============================================================================
 * FUNCTIONS
 *============================================================================*/
void attachServo(byte pin, int minPulse, int maxPulse)
{
  if (servoCount < MAX_SERVOS) {
    // reuse indexes of detached servos until all have been reallocated
    if (detachedServoCount > 0) {
      servoPinMap[pin] = detachedServos[detachedServoCount - 1];
      if (detachedServoCount > 0) detachedServoCount--;
    } else {
      servoPinMap[pin] = servoCount;
      servoCount++;
    }
    if (minPulse > 0 && maxPulse > 0) {
      servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse);
    } else {
      servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin));
    }
  } else {
    Firmata.sendString("Max servos attached");
  }
}
void detachServo(byte pin)
{
  servos[servoPinMap[pin]].detach();
  // if we're detaching the last servo, decrement the count
  // otherwise store the index of the detached servo
  if (servoPinMap[pin] == servoCount && servoCount > 0) {
    servoCount--;
  } else if (servoCount > 0) {
    // keep track of detached servos because we want to reuse their indexes
    // before incrementing the count of attached servos
    detachedServoCount++;
    detachedServos[detachedServoCount - 1] = servoPinMap[pin];
  }
  servoPinMap[pin] = 255;
}
void enableI2CPins()
{
  byte i;
  // is there a faster way to do this? would probaby require importing
  // Arduino.h to get SCL and SDA pins
  for (i = 0; i < TOTAL_PINS; i++) {
    if (IS_PIN_I2C(i)) {
      // mark pins as i2c so they are ignore in non i2c data requests
      setPinModeCallback(i, PIN_MODE_I2C);
    }
  }
  isI2CEnabled = true;
  Wire.begin();
}
/* disable the i2c pins so they can be used for other functions */
void disableI2CPins() {
  isI2CEnabled = false;
  // disable read continuous mode for all devices
  queryIndex = -1;
}
void readAndReportData(byte address, int theRegister, byte numBytes, byte stopTX) {
  // allow I2C requests that don't require a register read
  // for example, some devices using an interrupt pin to signify new data available
  // do not always require the register read so upon interrupt you call Wire.requestFrom()
  if (theRegister != I2C_REGISTER_NOT_SPECIFIED) {
    Wire.beginTransmission(address);
    wireWrite((byte)theRegister);
    Wire.endTransmission(stopTX); // default = true
    // do not set a value of 0
    if (i2cReadDelayTime > 0) {
      // delay is necessary for some devices such as WiiNunchuck
      delayMicroseconds(i2cReadDelayTime);
    }
  } else {
    theRegister = 0;  // fill the register with a dummy value
  }
  Wire.requestFrom(address, numBytes);  // all bytes are returned in requestFrom
  // check to be sure correct number of bytes were returned by slave
  if (numBytes < Wire.available()) {
    Firmata.sendString("I2C: Too many bytes received");
  } else if (numBytes > Wire.available()) {
    Firmata.sendString("I2C: Too few bytes received");
  }
  i2cRxData[0] = address;
  i2cRxData[1] = theRegister;
  for (int i = 0; i < numBytes && Wire.available(); i++) {
    i2cRxData[2 + i] = wireRead();
  }
  // send slave address, register and received bytes
  Firmata.sendSysex(SYSEX_I2C_REPLY, numBytes + 2, i2cRxData);
}
void outputPort(byte portNumber, byte portValue, byte forceSend)
{
  // pins not configured as INPUT are cleared to zeros
  portValue = portValue & portConfigInputs[portNumber];
  // only send if the value is different than previously sent
  if (forceSend || previousPINs[portNumber] != portValue) {
    Firmata.sendDigitalPort(portNumber, portValue);
    previousPINs[portNumber] = portValue;
  }
}
/* -----------------------------------------------------------------------------
 * check all the active digital inputs for change of state, then add any events
 * to the Serial output queue using Serial.print() */
void checkDigitalInputs(void)
{
  /* Using non-looping code allows constants to be given to readPort().
   * The compiler will apply substantial optimizations if the inputs
   * to readPort() are compile-time constants. */
  if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
  if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
  if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
  if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
  if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
  if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
  if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
  if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
  if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
  if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
  if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
  if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
  if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
  if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
  if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
  if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
}
// -----------------------------------------------------------------------------
/* sets the pin mode to the correct state and sets the relevant bits in the
 * two bit-arrays that track Digital I/O and PWM status
 */
void setPinModeCallback(byte pin, int mode)
{
  if (Firmata.getPinMode(pin) == PIN_MODE_IGNORE)
    return;
  if (Firmata.getPinMode(pin) == PIN_MODE_I2C && isI2CEnabled && mode != PIN_MODE_I2C) {
    // disable i2c so pins can be used for other functions
    // the following if statements should reconfigure the pins properly
    disableI2CPins();
  }
  if (IS_PIN_DIGITAL(pin) && mode != PIN_MODE_SERVO) {
    if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
      detachServo(pin);
    }
  }
  if (IS_PIN_ANALOG(pin)) {
    reportAnalogCallback(PIN_TO_ANALOG(pin), mode == PIN_MODE_ANALOG ? 1 : 0); // turn on/off reporting
  }
  if (IS_PIN_DIGITAL(pin)) {
    if (mode == INPUT || mode == PIN_MODE_PULLUP) {
      portConfigInputs[pin / 8] |= (1 << (pin & 7));
    } else {
      portConfigInputs[pin / 8] &= ~(1 << (pin & 7));
    }
  }
  Firmata.setPinState(pin, 0);
  switch (mode) {
    case PIN_MODE_ANALOG:
      if (IS_PIN_ANALOG(pin)) {
        if (IS_PIN_DIGITAL(pin)) {
          pinMode(PIN_TO_DIGITAL(pin), INPUT);    // disable output driver
#if ARDUINO <= 100
          // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
          digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
#endif
        }
        Firmata.setPinMode(pin, PIN_MODE_ANALOG);
      }
      break;
    case INPUT:
      if (IS_PIN_DIGITAL(pin)) {
        pinMode(PIN_TO_DIGITAL(pin), INPUT);    // disable output driver
#if ARDUINO <= 100
        // deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
        digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
#endif
        Firmata.setPinMode(pin, INPUT);
      }
      break;
    case PIN_MODE_PULLUP:
      if (IS_PIN_DIGITAL(pin)) {
        pinMode(PIN_TO_DIGITAL(pin), INPUT_PULLUP);
        Firmata.setPinMode(pin, PIN_MODE_PULLUP);
        Firmata.setPinState(pin, 1);
      }
      break;
    case OUTPUT:
      if (IS_PIN_DIGITAL(pin)) {
        if (Firmata.getPinMode(pin) == PIN_MODE_PWM) {
          // Disable PWM if pin mode was previously set to PWM.
          digitalWrite(PIN_TO_DIGITAL(pin), LOW);
        }
        pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
        Firmata.setPinMode(pin, OUTPUT);
      }
      break;
    case PIN_MODE_PWM:
      if (IS_PIN_PWM(pin)) {
        pinMode(PIN_TO_PWM(pin), OUTPUT);
        analogWrite(PIN_TO_PWM(pin), 0);
        Firmata.setPinMode(pin, PIN_MODE_PWM);
      }
      break;
    case PIN_MODE_SERVO:
      if (IS_PIN_DIGITAL(pin)) {
        Firmata.setPinMode(pin, PIN_MODE_SERVO);
        if (servoPinMap[pin] == 255 || !servos[servoPinMap[pin]].attached()) {
          // pass -1 for min and max pulse values to use default values set
          // by Servo library
          attachServo(pin, -1, -1);
        }
      }
      break;
    case PIN_MODE_I2C:
      if (IS_PIN_I2C(pin)) {
        // mark the pin as i2c
        // the user must call I2C_CONFIG to enable I2C for a device
        Firmata.setPinMode(pin, PIN_MODE_I2C);
      }
      break;
    case PIN_MODE_SERIAL:
#ifdef FIRMATA_SERIAL_FEATURE
      serialFeature.handlePinMode(pin, PIN_MODE_SERIAL);
#endif
      break;
    default:
      Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM
  }
  // TODO: save status to EEPROM here, if changed
}
/*
 * Sets the value of an individual pin. Useful if you want to set a pin value but
 * are not tracking the digital port state.
 * Can only be used on pins configured as OUTPUT.
 * Cannot be used to enable pull-ups on Digital INPUT pins.
 */
void setPinValueCallback(byte pin, int value)
{
  if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
    if (Firmata.getPinMode(pin) == OUTPUT) {
      Firmata.setPinState(pin, value);
      digitalWrite(PIN_TO_DIGITAL(pin), value);
    }
  }
}
void analogWriteCallback(byte pin, int value)
{
  if (pin < TOTAL_PINS) {
    switch (Firmata.getPinMode(pin)) {
      case PIN_MODE_SERVO:
        if (IS_PIN_DIGITAL(pin))
          servos[servoPinMap[pin]].write(value);
        Firmata.setPinState(pin, value);
        break;
      case PIN_MODE_PWM:
        if (IS_PIN_PWM(pin))
          analogWrite(PIN_TO_PWM(pin), value);
        Firmata.setPinState(pin, value);
        break;
    }
  }
}
void digitalWriteCallback(byte port, int value)
{
  byte pin, lastPin, pinValue, mask = 1, pinWriteMask = 0;
  if (port < TOTAL_PORTS) {
    // create a mask of the pins on this port that are writable.
    lastPin = port * 8 + 8;
    if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS;
    for (pin = port * 8; pin < lastPin; pin++) {
      // do not disturb non-digital pins (eg, Rx & Tx)
      if (IS_PIN_DIGITAL(pin)) {
        // do not touch pins in PWM, ANALOG, SERVO or other modes
        if (Firmata.getPinMode(pin) == OUTPUT || Firmata.getPinMode(pin) == INPUT) {
          pinValue = ((byte)value & mask) ? 1 : 0;
          if (Firmata.getPinMode(pin) == OUTPUT) {
            pinWriteMask |= mask;
          } else if (Firmata.getPinMode(pin) == INPUT && pinValue == 1 && Firmata.getPinState(pin) != 1) {
            // only handle INPUT here for backwards compatibility
#if ARDUINO > 100
            pinMode(pin, INPUT_PULLUP);
#else
            // only write to the INPUT pin to enable pullups if Arduino v1.0.0 or earlier
            pinWriteMask |= mask;
#endif
          }
          Firmata.setPinState(pin, pinValue);
        }
      }
      mask = mask << 1;
    }
    writePort(port, (byte)value, pinWriteMask);
  }
}</p><p>// -----------------------------------------------------------------------------
/* sets bits in a bit array (int) to toggle the reporting of the analogIns
 */
//void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
//}
void reportAnalogCallback(byte analogPin, int value)
{
  if (analogPin < TOTAL_ANALOG_PINS) {
    if (value == 0) {
      analogInputsToReport = analogInputsToReport & ~ (1 << analogPin);
    } else {
      analogInputsToReport = analogInputsToReport | (1 << analogPin);
      // prevent during system reset or all analog pin values will be reported
      // which may report noise for unconnected analog pins
      if (!isResetting) {
        // Send pin value immediately. This is helpful when connected via
        // ethernet, wi-fi or bluetooth so pin states can be known upon
        // reconnecting.
        Firmata.sendAnalog(analogPin, analogRead(analogPin));
      }
    }
  }
  // TODO: save status to EEPROM here, if changed
}
void reportDigitalCallback(byte port, int value)
{
  if (port < TOTAL_PORTS) {
    reportPINs[port] = (byte)value;
    // Send port value immediately. This is helpful when connected via
    // ethernet, wi-fi or bluetooth so pin states can be known upon
    // reconnecting.
    if (value) outputPort(port, readPort(port, portConfigInputs[port]), true);
  }
  // do not disable analog reporting on these 8 pins, to allow some
  // pins used for digital, others analog.  Instead, allow both types
  // of reporting to be enabled, but check if the pin is configured
  // as analog when sampling the analog inputs.  Likewise, while
  // scanning digital pins, portConfigInputs will mask off values from any
  // pins configured as analog
}
/*==============================================================================
 * SYSEX-BASED commands
 *============================================================================*/
void sysexCallback(byte command, byte argc, byte *argv)
{
  byte mode;
  byte stopTX;
  byte slaveAddress;
  byte data;
  int slaveRegister;
  unsigned int delayTime;
  switch (command) {
    case I2C_REQUEST:
      mode = argv[1] & I2C_READ_WRITE_MODE_MASK;
      if (argv[1] & I2C_10BIT_ADDRESS_MODE_MASK) {
        Firmata.sendString("10-bit addressing not supported");
        return;
      }
      else {
        slaveAddress = argv[0];
      }
      // need to invert the logic here since 0 will be default for client
      // libraries that have not updated to add support for restart tx
      if (argv[1] & I2C_END_TX_MASK) {
        stopTX = I2C_RESTART_TX;
      }
      else {
        stopTX = I2C_STOP_TX; // default
      }
      switch (mode) {
        case I2C_WRITE:
          Wire.beginTransmission(slaveAddress);
          for (byte i = 2; i < argc; i += 2) {
            data = argv[i] + (argv[i + 1] << 7);
            wireWrite(data);
          }
          Wire.endTransmission();
          delayMicroseconds(70);
          break;
        case I2C_READ:
          if (argc == 6) {
            // a slave register is specified
            slaveRegister = argv[2] + (argv[3] << 7);
            data = argv[4] + (argv[5] << 7);  // bytes to read
          }
          else {
            // a slave register is NOT specified
            slaveRegister = I2C_REGISTER_NOT_SPECIFIED;
            data = argv[2] + (argv[3] << 7);  // bytes to read
          }
          readAndReportData(slaveAddress, (int)slaveRegister, data, stopTX);
          break;
        case I2C_READ_CONTINUOUSLY:
          if ((queryIndex + 1) >= I2C_MAX_QUERIES) {
            // too many queries, just ignore
            Firmata.sendString("too many queries");
            break;
          }
          if (argc == 6) {
            // a slave register is specified
            slaveRegister = argv[2] + (argv[3] << 7);
            data = argv[4] + (argv[5] << 7);  // bytes to read
          }
          else {
            // a slave register is NOT specified
            slaveRegister = (int)I2C_REGISTER_NOT_SPECIFIED;
            data = argv[2] + (argv[3] << 7);  // bytes to read
          }
          queryIndex++;
          query[queryIndex].addr = slaveAddress;
          query[queryIndex].reg = slaveRegister;
          query[queryIndex].bytes = data;
          query[queryIndex].stopTX = stopTX;
          break;
        case I2C_STOP_READING:
          byte queryIndexToSkip;
          // if read continuous mode is enabled for only 1 i2c device, disable
          // read continuous reporting for that device
          if (queryIndex <= 0) {
            queryIndex = -1;
          } else {
            queryIndexToSkip = 0;
            // if read continuous mode is enabled for multiple devices,
            // determine which device to stop reading and remove it's data from
            // the array, shifiting other array data to fill the space
            for (byte i = 0; i < queryIndex + 1; i++) {
              if (query[i].addr == slaveAddress) {
                queryIndexToSkip = i;
                break;
              }
            }
            for (byte i = queryIndexToSkip; i < queryIndex + 1; i++) {
              if (i < I2C_MAX_QUERIES) {
                query[i].addr = query[i + 1].addr;
                query[i].reg = query[i + 1].reg;
                query[i].bytes = query[i + 1].bytes;
                query[i].stopTX = query[i + 1].stopTX;
              }
            }
            queryIndex--;
          }
          break;
        default:
          break;
      }
      break;
    case I2C_CONFIG:
      delayTime = (argv[0] + (argv[1] << 7));
      if (delayTime > 0) {
        i2cReadDelayTime = delayTime;
      }
      if (!isI2CEnabled) {
        enableI2CPins();
      }
      break;
    case SERVO_CONFIG:
      if (argc > 4) {
        // these vars are here for clarity, they'll optimized away by the compiler
        byte pin = argv[0];
        int minPulse = argv[1] + (argv[2] << 7);
        int maxPulse = argv[3] + (argv[4] << 7);
        if (IS_PIN_DIGITAL(pin)) {
          if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) {
            detachServo(pin);
          }
          attachServo(pin, minPulse, maxPulse);
          setPinModeCallback(pin, PIN_MODE_SERVO);
        }
      }
      break;
    case SAMPLING_INTERVAL:
      if (argc > 1) {
        samplingInterval = argv[0] + (argv[1] << 7);
        if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) {
          samplingInterval = MINIMUM_SAMPLING_INTERVAL;
        }
      } else {
        //Firmata.sendString("Not enough data");
      }
      break;
    case EXTENDED_ANALOG:
      if (argc > 1) {
        int val = argv[1];
        if (argc > 2) val |= (argv[2] << 7);
        if (argc > 3) val |= (argv[3] << 14);
        analogWriteCallback(argv[0], val);
      }
      break;
    case CAPABILITY_QUERY:
      Firmata.write(START_SYSEX);
      Firmata.write(CAPABILITY_RESPONSE);
      for (byte pin = 0; pin < TOTAL_PINS; pin++) {
        if (IS_PIN_DIGITAL(pin)) {
          Firmata.write((byte)INPUT);
          Firmata.write(1);
          Firmata.write((byte)PIN_MODE_PULLUP);
          Firmata.write(1);
          Firmata.write((byte)OUTPUT);
          Firmata.write(1);
        }
        if (IS_PIN_ANALOG(pin)) {
          Firmata.write(PIN_MODE_ANALOG);
          Firmata.write(10); // 10 = 10-bit resolution
        }
        if (IS_PIN_PWM(pin)) {
          Firmata.write(PIN_MODE_PWM);
          Firmata.write(DEFAULT_PWM_RESOLUTION);
        }
        if (IS_PIN_DIGITAL(pin)) {
          Firmata.write(PIN_MODE_SERVO);
          Firmata.write(14);
        }
        if (IS_PIN_I2C(pin)) {
          Firmata.write(PIN_MODE_I2C);
          Firmata.write(1);  // TODO: could assign a number to map to SCL or SDA
        }
#ifdef FIRMATA_SERIAL_FEATURE
        serialFeature.handleCapability(pin);
#endif
        Firmata.write(127);
      }
      Firmata.write(END_SYSEX);
      break;
    case PIN_STATE_QUERY:
      if (argc > 0) {
        byte pin = argv[0];
        Firmata.write(START_SYSEX);
        Firmata.write(PIN_STATE_RESPONSE);
        Firmata.write(pin);
        if (pin < TOTAL_PINS) {
          Firmata.write(Firmata.getPinMode(pin));
          Firmata.write((byte)Firmata.getPinState(pin) & 0x7F);
          if (Firmata.getPinState(pin) & 0xFF80) Firmata.write((byte)(Firmata.getPinState(pin) >> 7) & 0x7F);
          if (Firmata.getPinState(pin) & 0xC000) Firmata.write((byte)(Firmata.getPinState(pin) >> 14) & 0x7F);
        }
        Firmata.write(END_SYSEX);
      }
      break;
    case ANALOG_MAPPING_QUERY:
      Firmata.write(START_SYSEX);
      Firmata.write(ANALOG_MAPPING_RESPONSE);
      for (byte pin = 0; pin < TOTAL_PINS; pin++) {
        Firmata.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
      }
      Firmata.write(END_SYSEX);
      break;
    case SERIAL_MESSAGE:
#ifdef FIRMATA_SERIAL_FEATURE
      serialFeature.handleSysex(command, argc, argv);
#endif
      break;
  }
}
/*==============================================================================
 * SETUP()
 *============================================================================*/
void systemResetCallback()
{
  isResetting = true;
  // initialize a defalt state
  // TODO: option to load config from EEPROM instead of default
#ifdef FIRMATA_SERIAL_FEATURE
  serialFeature.reset();
#endif
  if (isI2CEnabled) {
    disableI2CPins();
  }
  for (byte i = 0; i < TOTAL_PORTS; i++) {
    reportPINs[i] = false;    // by default, reporting off
    portConfigInputs[i] = 0;  // until activated
    previousPINs[i] = 0;
  }
  for (byte i = 0; i < TOTAL_PINS; i++) {
    // pins with analog capability default to analog input
    // otherwise, pins default to digital output
    if (IS_PIN_ANALOG(i)) {
      // turns off pullup, configures everything
      setPinModeCallback(i, PIN_MODE_ANALOG);
    } else if (IS_PIN_DIGITAL(i)) {
      // sets the output to 0, configures portConfigInputs
      setPinModeCallback(i, OUTPUT);
    }
    servoPinMap[i] = 255;
  }
  // by default, do not report any analog inputs
  analogInputsToReport = 0;
  detachedServoCount = 0;
  servoCount = 0;
  /* send digital inputs to set the initial state on the host computer,
   * since once in the loop(), this firmware will only send on change */
  /*
  TODO: this can never execute, since no pins default to digital input
        but it will be needed when/if we support EEPROM stored config
  for (byte i=0; i < TOTAL_PORTS; i++) {
    outputPort(i, readPort(i, portConfigInputs[i]), true);
  }
  */
  isResetting = false;
}
</p><pre><p>int Pump_Time1 = 3000 ; // Here we declare the time for the alcohol pumps. change here, and it changes them all<br>int Pump_Time2 = 10000 ; // Here we declare the time for the soda pumps. change here, and it changes them all.
int Exit_Time  = 5000 ;  // time for exit after ended drink from node-red 
void setup()
{
  Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
  Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
  Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
  Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
  Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
  Firmata.attach(SET_PIN_MODE, setPinModeCallback);
  Firmata.attach(SET_DIGITAL_PIN_VALUE, setPinValueCallback);
  Firmata.attach(START_SYSEX, sysexCallback);
  Firmata.attach(SYSTEM_RESET, systemResetCallback);
  // to use a port other than Serial, such as Serial1 on an Arduino Leonardo or Mega,
  // Call begin(baud) on the alternate serial port and pass it to Firmata to begin like this:
  // Serial1.begin(57600);
  // Firmata.begin(Serial1);
  // However do not do this if you are using SERIAL_MESSAGE
pinMode(22, OUTPUT); //LED for cola valgt
   pinMode(23, OUTPUT); //LED for Fanta valgt
   pinMode(24, OUTPUT); //LED for Sprite valgt
   pinMode(25, OUTPUT); //LED for Rom valgt
   pinMode(26, OUTPUT); //LED for Vodka valgt
   pinMode(27, OUTPUT); //LED for Gin valgt
  pinMode(12, OUTPUT); //LED LIGHT
  
  pinMode(28, OUTPUT); //pumpe for cola
  pinMode(29, OUTPUT); //pumpe for Fanta
  pinMode(30, OUTPUT); //pumpe for Sprite
  pinMode(31, OUTPUT); //pumpe for Rom                                     // You can change the in- and output as you want // 
  pinMode(32, OUTPUT); //pumpe for Vodka
  pinMode(33, OUTPUT); //pumpe for Gin
  
  pinMode(2, INPUT_PULLUP); // ON-OFF-ON Switch for cola
  pinMode(3, INPUT_PULLUP);  //ON-OFF-ON Switch for Fanta
  pinMode(4, INPUT_PULLUP); //ON-OFF-ON Switch for Sprite
  
  pinMode(5, INPUT_PULLUP); //ON-OFF-ON Switch for ROM
  pinMode(6, INPUT_PULLUP); //ON-OFF-ON Switch for VODKA
  pinMode(7, INPUT_PULLUP);  //ON-OFF-ON Switch for GIN
  pinMode(40, INPUT);   // Aktivering fra Node-Red - Blanding 1 
  pinMode(41, INPUT);   // Aktivering fra Node-Red - Blanding 2 
  pinMode(42, INPUT);   // Aktivering fra Node-Red - Blanding 3 
  pinMode(43, OUTPUT);  // Aktivering fra Node-Red - Lampe 1  
  pinMode(44, OUTPUT);  // Aktivering fra Node-Red - Lampe 2 
  pinMode(45, OUTPUT);  // Aktivering fra Node-Red - Lampe 3  
  
  Firmata.begin(57600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for ATmega32u4-based boards and Arduino 101
  }
  systemResetCallback();  // reset to default config
}
/*==============================================================================
 * LOOP()
 *============================================================================*/
void loop()
{
  byte pin, analogPin;
  /* DIGITALREAD - as fast as possible, check for changes and output them to the
   * FTDI buffer using Serial.print()  */
  checkDigitalInputs();
  /* STREAMREAD - processing incoming messagse as soon as possible, while still
   * checking digital inputs.  */
  while (Firmata.available())
    Firmata.processInput();
  // TODO - ensure that Stream buffer doesn't go over 60 bytes
  currentMillis = millis();
  if (currentMillis - previousMillis > samplingInterval) {
    previousMillis += samplingInterval;
    /* ANALOGREAD - do all analogReads() at the configured sampling interval */
    for (pin = 0; pin < TOTAL_PINS; pin++) {
      if (IS_PIN_ANALOG(pin) && Firmata.getPinMode(pin) == PIN_MODE_ANALOG) {
        analogPin = PIN_TO_ANALOG(pin);
        if (analogInputsToReport & (1 << analogPin)) {
          Firmata.sendAnalog(analogPin, analogRead(analogPin));
        }
      }
    }
    // report i2c data for all device with read continuous mode enabled
    if (queryIndex > -1) {
      for (byte i = 0; i < queryIndex + 1; i++) {
        readAndReportData(query[i].addr, query[i].reg, query[i].bytes, query[i].stopTX);
      }
    }
  }
#ifdef FIRMATA_SERIAL_FEATURE
  serialFeature.update();
#endif</p><p>//Aktivering af LED indikering 
if (digitalRead(2) == LOW ){
  digitalWrite(22, HIGH);// LED COLA ACTIVATED //
  Serial.println("COLA VALGT");
}
else{ 
  digitalWrite(22, LOW);
}</p><p>if (digitalRead(3) == LOW ){
  digitalWrite(23, HIGH);             // LED Fanta ACTIVATED //
  Serial.println("FANTA VALGT");
}
else{ 
  digitalWrite(23, LOW);
}</p><p>if (digitalRead(4) == LOW ){
  digitalWrite(24, HIGH);            // LED Sprite ACTIVATED //
  Serial.println("Sprite VALGT");
}
else{ 
  digitalWrite(24, LOW);
}</p><p>if (digitalRead(5) == LOW ){
  digitalWrite(25, HIGH);           // LED Rom ACTIVATED //
    Serial.println("ROM VALGT");
}
else{ 
  digitalWrite(25, LOW);
}</p><p>if (digitalRead(6) == LOW ){
  digitalWrite(26, HIGH);          // LED Vodka ACTIVATED //
    Serial.println("Vodka VALGT");
}
else{ 
  digitalWrite(26, LOW);
}</p><p>if (digitalRead(7) == LOW ){
  digitalWrite(27, HIGH);          // LED GIN ACTIVATED //
    Serial.println("Gin VALGT");
}
else{ 
  digitalWrite(27, LOW);
}</p><p>//--------------------------------------- Under here, we have the different kinds of mixes you can make ---------------------------------// 
// The describsion of the code is made at the first on, then the others are the same, with different outputs //
// COLA + VODKA MIX //
if (digitalRead(2) == LOW && digitalRead(6)== LOW && digitalRead(8)== LOW && digitalRead(7)== HIGH && digitalRead(5)== HIGH){
    digitalWrite(32, HIGH);            // ROM Relay is on
      Serial.println("Vodka Doseres"); // Prints "vodka doseres in the serial monitor (9600) 
    delay(Pump_Time1);                 // Here is the time for the alcohol pump, the first one we declared at the start  
    Serial.println("Cola Doseres");    // Prints " Cola doseres" in the serial monitor (9600)
     digitalWrite(28, HIGH);           // Sets Cola relay On
    digitalWrite(32, LOW);             // Sets Vodka relay off
    delay(Pump_Time2);                 // Here is the time for the soda pump, the second one we declared at the start
    Serial.println("Drink finish");    // Prints " Drinks finish" in the serial monitor (9600)
    digitalWrite(28, LOW);             // Sets Cola relay off
    }
    else {
      digitalWrite(32, LOW);
      digitalWrite(28, LOW);
        Serial.println("STANDBY");
        delay(100);
    }
    // COLA + ROM MIX //
    
  if (digitalRead(2) == LOW && digitalRead(5)== LOW && digitalRead(8)== LOW && digitalRead(7)== HIGH && digitalRead(6)== HIGH){
    digitalWrite(31, HIGH);  // ROM ON
      Serial.println("Rom Doseres");
    delay(Pump_Time1);
    Serial.println("Cola Doseres");
     digitalWrite(28, HIGH); // COLA ON
    digitalWrite(31, LOW);   // ROM OFF
    delay(Pump_Time2); 
    Serial.println("Drink færdig");
    digitalWrite(28, LOW);   // COLA OFF
    }
    else {
      digitalWrite(31, LOW);
      digitalWrite(28, LOW);
        Serial.println("STANDBY");
        delay(100);
    }
// COLA + GIN MIX //
 if (digitalRead(2) == LOW && digitalRead(5)== HIGH && digitalRead(8)== LOW && digitalRead(7)== LOW && digitalRead(6)== HIGH){
    digitalWrite(33, HIGH);  // ROM ON
      Serial.println("Rom Doseres");
    delay(Pump_Time1);
    Serial.println("Cola Doseres");
     digitalWrite(28, HIGH); // COLA ON
    digitalWrite(33, LOW);   // ROM OFF
    delay(Pump_Time2); 
    Serial.println("Drink færdig");
    digitalWrite(28, LOW);   // COLA OFF
    }
    else {
      digitalWrite(33, LOW);
      digitalWrite(28, LOW);
        Serial.println("STANDBY");
        delay(100);
    }
    
 // Fanta + Rom MIX //
 
    if (digitalRead(3) == LOW && digitalRead(5)== LOW && digitalRead(8)== LOW && digitalRead(7)== HIGH && digitalRead(6)== HIGH){
    digitalWrite(31, HIGH);  // ROM ON
      Serial.println("Rom Doseres");
    delay(Pump_Time1);
    Serial.println("Cola Doseres");
     digitalWrite(28, HIGH); // COLA ON
    digitalWrite(31, LOW);   // ROM OFF
    delay(Pump_Time2); 
    Serial.println("Drink færdig");
    digitalWrite(28, LOW);   // COLA OFF
    }
    else {
      digitalWrite(31, LOW);
      digitalWrite(28, LOW);
        Serial.println("STANDBY");
        delay(100);
    }
   // Fanta + Vodka MIX //
       if (digitalRead(3) == LOW && digitalRead(5)== HIGH && digitalRead(8)== LOW && digitalRead(7)== HIGH && digitalRead(6)== LOW){
    digitalWrite(32, HIGH);  // ROM ON
      Serial.println("Rom Doseres");
    delay(Pump_Time1);
    Serial.println("Cola Doseres");
     digitalWrite(28, HIGH); // COLA ON
    digitalWrite(32, LOW);   // ROM OFF
    delay(Pump_Time2); 
    Serial.println("Drink færdig");
    digitalWrite(28, LOW);   // COLA OFF
    }
    else {
      digitalWrite(32, LOW);
      digitalWrite(28, LOW);
        Serial.println("STANDBY");
        delay(100);
    }
    // Fanta + Gin MIX //
    
        if (digitalRead(3) == LOW && digitalRead(5)== HIGH && digitalRead(8)== LOW && digitalRead(7)== LOW && digitalRead(6)== HIGH){
    digitalWrite(33, HIGH);  // ROM ON
      Serial.println("Rom Doseres");
    delay(Pump_Time1);
    Serial.println("Cola Doseres");
     digitalWrite(28, HIGH); // COLA ON
    digitalWrite(33, LOW);   // ROM OFF
    delay(Pump_Time2); 
    Serial.println("Drink færdig");
    digitalWrite(28, LOW);   // COLA OFF
    }
    else {
      digitalWrite(33, LOW);
      digitalWrite(28, LOW);
        Serial.println("STANDBY");
        delay(100);
    }
 // Sprite + Rom MIX //
    
       if (digitalRead(4) == LOW && digitalRead(5)== LOW && digitalRead(8)== LOW && digitalRead(7)== HIGH && digitalRead(6)== HIGH){
    digitalWrite(31, HIGH);  // ROM ON
      Serial.println("Rom Doseres");
    delay(Pump_Time1);
    Serial.println("Sprite Doseres");
     digitalWrite(30, HIGH); // COLA ON
    digitalWrite(31, LOW);   // ROM OFF
    delay(Pump_Time2); 
    Serial.println("Drink færdig");
    digitalWrite(30, LOW);   // COLA OFF
    }
    else {
      digitalWrite(30, LOW);
      digitalWrite(31, LOW);
        Serial.println("STANDBY");
        delay(100);
    }
   // Sprite + Vodka MIX //
   
    if (digitalRead(4) == LOW && digitalRead(5)== HIGH && digitalRead(8)== LOW && digitalRead(7)== HIGH && digitalRead(6)== LOW){
    digitalWrite(32, HIGH);  // ROM ON
      Serial.println("Rom Doseres");
    delay(Pump_Time1);
    Serial.println("Sprite Doseres");
     digitalWrite(30, HIGH); // COLA ON
    digitalWrite(32, LOW);   // ROM OFF
    delay(Pump_Time2); 
    Serial.println("Drink færdig");
    digitalWrite(30, LOW);   // COLA OFF
    }
    else {
      digitalWrite(30, LOW);
      digitalWrite(32, LOW);
        Serial.println("STANDBY");
        delay(100);
    }
    
   // Sprite + Gin MIX //
   
      if (digitalRead(4) == LOW && digitalRead(5)== HIGH && digitalRead(8)== LOW && digitalRead(7)== LOW && digitalRead(6)== HIGH){
    digitalWrite(33, HIGH);  // ROM ON
      Serial.println("Rom Doseres");
    delay(Pump_Time1);
    Serial.println("Sprite Doseres");
     digitalWrite(30, HIGH); // COLA ON
    digitalWrite(33, LOW);   // ROM OFF
    delay(Pump_Time2); 
    Serial.println("Drink færdig");
    digitalWrite(30, LOW);   // COLA OFF
    }
    else {
      digitalWrite(30, LOW);
      digitalWrite(33, LOW);
        Serial.println("STANDBY");
        delay(100);
    }
    
// Code for optimizing Drinkster //
 // pinMode(28, OUTPUT); //pumpe for cola
 // pinMode(29, OUTPUT); //pumpe for Fanta
 // pinMode(30, OUTPUT); //pumpe for Sprite
 // pinMode(31, OUTPUT); //pumpe for Rom                                     // You can change the in- and output as you want // 
 // pinMode(32, OUTPUT); //pumpe for Vodka
 // pinMode(33, OUTPUT); //pumpe for Gin
// BLANDING 1 - ROM & COLA // 
 if( digitalRead(40)){
  digitalWrite(31, HIGH);  // ROM ON
      Serial.println("Rom Doseres");
    delay(Pump_Time1);
    Serial.println("COLA Doseres");
     digitalWrite(28, HIGH); // COLA ON
    digitalWrite(31, LOW);   // ROM OFF
    delay(Pump_Time2); 
    Serial.println("Drink færdig");
    digitalWrite(28, LOW);  // ROM ON
    digitalWrite(40, LOW);
    delay(Exit_Time);  
 }
 
// BLANDING 2- Gin-LEMON //
  if( digitalRead(41)){
  digitalWrite(33, HIGH);  // GIN ON
      Serial.println("Rom Doseres");
    delay(Pump_Time1);
    Serial.println("Fanta Doseres");
     digitalWrite(29, HIGH); // TONIC ON
    digitalWrite(33, LOW);   
    delay(Pump_Time2); 
    Serial.println("Drink færdig");
    digitalWrite(29, LOW);  // ROM ON
    digitalWrite(41, LOW);  
 }
// BLANDING 3 Vodka-Sprite // 
  if( digitalRead(42)){
  digitalWrite(32, HIGH);  // Vodka ON
      Serial.println("Vodka Doseres");
    delay(Pump_Time1);
    Serial.println("Sprite Doseres");
     digitalWrite(30, HIGH); // COLA ON
    digitalWrite(32, LOW);   // ROM OFF
    delay(Pump_Time2); 
    Serial.println("Drink færdig");
    digitalWrite(30, LOW);  // ROM ON
    digitalWrite(42, LOW);  
 }
}</p>







Step 5: Node-RED

Her ses vores Node-Red flow. Flowet kan downloades via det vedlagte dokument, og kan derefter importeres og bruges.

Vi har yderligere været inde og generer en QR kode, som gør det muligt at bruge sin smartphone til bestilling. Ved at scanne QR koden, som opretter link mellem vores IP, kan man derefter kan man tilgå den samme data fra mobilen, som fra computeren. For at dette kan lade sig gøre, skal ens mobil være på samme netværk som vores Raspberry pi 3.

Attachments

Step 6: Tabel-valg

Som Database har vi valgt at bruge WampServer, som er et onlinetilgængelig database, som man kan ligge lokalt på sin computer.

Vi har opbygget vores database med fem tabeller

  • ·Kunde
  1. Kunde_id
  2. Fornavn
  3. Efternavn
  • ·Salg
  1. Salg_ID
  2. Rom og Cola
  3. Vodka og Fanta
  4. Gin og Lemon
  • Lokation
  1. Lokation_ID
  2. Adresse
  3. Dato/tid
  • Lager
  1. Cola
  2. Fanta
  3. Lemon
  4. Rom
  5. Vodka
  6. Gin
  • Statistik
  1. Rom og Cola
  2. Vodka og Fanta
  3. Gin og Lemon

Dette er gjort for at opdele dataene i de forskellige elementer og gøre det muligt at udvide nemmere fremover i databasen.

Der er blevet oprettet ”kunde_id” i kunde tabellen som fungere som primary key, det samme er gjort i salg og lokationer. Vi har så lavet relationer mellem kunde_id og salg/lokationer, så vi kan trække data omkring 1 kunde og hans lokation i vores presentation form i Visual Studio.

Step 7: Visual Studio

(Beskrivelse af programdelene er knyttet til vores billeder)

Som et led i vores projekt, har vi via Visual studio, udviklet en konsol, som gør det muligt at tilføje en ny bruger til vores database. Oplysningerne indtastes i deres respektive felter, og der trykkes herefter på "opret bruger", hvorefter disse oplysninger, ligges over i vores database.

Der er samtidigt oprettet et "datagrid" view, som gør det muligt at hente data fra vores database. "Datagrid'et" opdateres ved at trykke "opdater database", hvorefter denne opdateres med de nyeste oplysninger der findes i databasen.

The code

<p>using System;</p><p>using System.Collections.Generic;</p><p>using System.ComponentModel;</p><p>using System.Data;</p><p>using System;</p><p>using System.Collections.Generic;</p><p>using System.ComponentModel;</p><p>using System.Data;</p><p>using System.Drawing;</p><p>using System.Linq;</p><p>using System.Text;</p><p>using System.Threading.Tasks;</p><p>using System.Windows.Forms;</p><p>using System.Data;</p><p>using MySql.Data;</p><p>using MySql.Web;</p><p>using MySql.Data.MySqlClient;</p><p>namespace Drinkster_2._1</p><p>{</p><p>    public partial class Name_box : Form</p><p>    {</p><p>        MySqlDataAdapter daData;</p><p>        DataSet dsData;</p><p>        public Name_box()</p><p>        {</p><p>            InitializeComponent();</p><p>        }</p><p>        void Fillcombo()</p><p>        {</p><p>            string ConnStr = "server=localhost;userid=root;password='';database=drinkster";</p><p>            string Query = "select * from
drinkster.kunde;";</p><p>            MySqlConnection conn = new MySqlConnection(ConnStr);</p><p>            try</p><p>            {</p><p>            }</p><p>            catch (Exception ex)</p><p>            {</p><p>                MessageBox.Show(ex.Message);</p><p>            }</p><p>        }</p><p>        private void Form1_Load(object sender, EventArgs e)</p><p>        {</p><p>            string ConnStr = "server=localhost;userid=root;password='';database=drinkster";</p><p>            MySqlConnection conn = new MySqlConnection(ConnStr);</p><p>            try</p><p>            {</p><p>                label1.Text = "connecting
to Mysql Data Base";</p><p>                Updating_Label.Text = "Press
Update";</p><p>                conn.Open();</p><p>                string Query = "SELECT `kunde`.`id_kunde`,
`kunde`.`Fornavn`, `kunde`.`Efternavn`, `salg`.`Type`, `salg`.`Antal`,
`lokation`.`Adresse`, `lokation`.`Dato` FROM `kunde` LEFT JOIN `lokation` ON
`kunde`.`id_kunde` = `lokation`.`id_lokation` LEFT JOIN `salg` ON
`kunde`.`id_kunde` = `salg`.`id_salg` ";</p><p>                daData = new MySqlDataAdapter(Query,
conn);</p><p>                MySqlCommandBuilder cb = new MySqlCommandBuilder(daData);</p><p>                dsData = new DataSet();</p><p>                daData.Fill(dsData, "kunde");</p><p>                dataGridView1.DataSource =
dsData;</p><p>                dataGridView1.DataMember = "kunde";</p><p>            }</p><p>            catch (Exception ex)</p><p>            {</p><p>                MessageBox.Show(ex.Message);</p><p>            }</p><p>        }</p><p>           private void button1_Click(object sender, EventArgs e)</p><p>           {</p><p>            string ConnStr = "server=localhost;userid=root;password='';database=drinkster";</p><p>            MySqlConnection conn = new MySqlConnection(ConnStr);</p><p>            conn.Open();</p><p>            string Query = "SELECT
`kunde`.`id_kunde`, `kunde`.`Fornavn`, `kunde`.`Efternavn`, `salg`.`Type`,
`salg`.`Antal`, `lokation`.`Adresse`, `lokation`.`Dato` FROM `kunde` LEFT JOIN
`lokation` ON `kunde`.`id_kunde` = `lokation`.`id_lokation` LEFT JOIN `salg` ON
`kunde`.`id_kunde` = `salg`.`id_salg` ";</p><p>            daData = new MySqlDataAdapter(Query,
conn);</p><p>            MySqlCommandBuilder cb = new MySqlCommandBuilder(daData);</p><p>            dsData = new DataSet();</p><p>            daData.Fill(dsData, "kunde");</p><p>            dataGridView1.DataSource = dsData;</p><p>            dataGridView1.DataMember = "kunde";</p><p>            daData.Update(dsData, "kunde");</p><p>            Updating_Label.Text = "Database
is Updated" ;</p><p>           }</p><p>        private void Opret_bruger_button_Click(object sender, EventArgs e)</p><p>        {</p><p>            string ConnStr = "server=localhost;userid=root;password='';database=drinkster";</p><p>            MySqlConnection conn = new MySqlConnection(ConnStr);</p><p>            conn.Open();</p><p>            string name = NameBox.Text.ToString();</p><p>            string efternavn =
LastName_Box.Text.ToString();</p><p>            string by =
Location_box.Text.ToString();</p><p>            string insert = " INSERT INTO  kunde (Fornavn, Efternavn) VALUES (@0,@1
)";</p><p>            MySqlCommand insertcmd =
new MySqlCommand(insert,
conn);</p><p>            insertcmd.Parameters.Add(new MySqlParameter("0", name ));</p><p>            insertcmd.Parameters.Add(new MySqlParameter("1",
efternavn));</p><p>            insertcmd.ExecuteNonQuery();</p><p>            string insert1 = " INSERT INTO  lokation (Adresse) VALUES (@0)";</p><p>            MySqlCommand insert1cmd
= new MySqlCommand(insert1,
conn);</p><p>            insert1cmd.Parameters.Add(new MySqlParameter("0", by));</p><p>            insert1cmd.ExecuteNonQuery();</p><p>            // insert1cmd.Parameters.Add(new
MySqlParameter("1", "2018-10-2" ));</p><p>        }</p><p>        private void Location_box_TextChanged(object sender, EventArgs e)</p><p>        {</p><p>        }</p><p>    }</p><p>}</p><br>