Rishabh Verma
Published © GPL3+

Voice-Activated Vending Machine

Voice-activated vending machine for food trucks and fast food joints that uses facial recognition to identifying customers.

IntermediateProtip12 hours2,930

Things used in this project

Hardware components

MATRIX Creator
MATRIX Labs MATRIX Creator
×1
Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
×1
Camera (generic)
×1
DC motor (generic)
×2
Relay Module (Generic)
×1

Software apps and online services

Snips AIR
Snips AIR

Story

Read more

Code

mqtthelper.cpp

C/C++
contains mqtt related functions
#include <iostream>
#include <string.h>
#include "MQTTClient.h"
#include "mqtthelper.h"

volatile double msg = 0;
MQTTClient_deliveryToken deliveredtoken;
  MQTTClient client;
  MQTTClient_message pubmsg = MQTTClient_message_initializer;
  MQTTClient_deliveryToken token;

int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{

    /*printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("   message: ");
    putchar('\n');

   */
   //std::cout<<(char*)message->payload;
   msg = std::stod((char*)message->payload);
   
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);


    return 1;
}
void delivered(void *context, MQTTClient_deliveryToken dt)
{
    deliveredtoken = dt;
}

void connlost(void *context, char *cause)
{
    printf("\n[Everloop]:  Connection lost\n");
    printf("     cause: %s\n", cause);
}
void initMqtt(char *ADDRESS,char *CLIENTID,char *TOPIC,int QOS){

  MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
  int rc;
  int ch;
  MQTTClient_create(&client, ADDRESS, CLIENTID,MQTTCLIENT_PERSISTENCE_NONE, NULL);
  conn_opts.keepAliveInterval = 20;
  conn_opts.cleansession = 1;
  MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered);
  if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
  {
      printf("[Everloop]:  Failed to connect, return code %d\n", rc);
      exit(EXIT_FAILURE);
  }
  std::cout<<"[Everloop]:  Connected"<<std::endl;
  //printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n", TOPIC, CLIENTID, QOS);
  MQTTClient_subscribe(client, TOPIC, QOS);
}
void publishStatus(char *topic,char *payload){
  int rc;
   pubmsg.payload = payload;
   pubmsg.payloadlen = 1;
   pubmsg.qos = 0;
   pubmsg.retained = 0;
    deliveredtoken = 0;
    MQTTClient_publishMessage(client,topic, &pubmsg, &token);
    printf("Waiting for publication of %s\n"
            "on topic %s \n",
            payload, topic);
    while(deliveredtoken != token);
    printf("[paymentny]Message with delivery\n");
}

mqtthelper.h

C Header File
#ifndef MQTTHELPER_H
#define MQTTHELPER_H


#include "MQTTClient.h"


#define TIMEOUT     10000L

extern volatile double msg;
extern MQTTClient_deliveryToken deliveredtoken;
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message);
void delivered(void *context, MQTTClient_deliveryToken dt);
void connlost(void *context, char *cause);
void initMqtt(char *ADDRESS,char *CLIENTID,char *TOPIC,int QOS);
void publishStatus(char *topic,char *payload);
#endif

nfc.cpp

C/C++
nfc card reader
/////////////////////////
// INCLUDE STATEMENTS //
///////////////////////

// For console output
#include <iostream>
// For sleep
#include <chrono>
#include <thread>
#include <sstream>
#include <fstream>
#include <string>
#include <unistd.h>
#include <ctime>
#include "mqtthelper.h"
// For using NFC
#include "matrix_nfc/nfc.h"
#include "matrix_nfc/nfc_data.h"
#include "matrix_hal/matrixio_bus.h"

char ADDRESS[] = "localhost:1883";
char CLIENTID[] = "default";
char TOPIC[] = "payment/start";
char topic_pub_status[] = "payment/status";

int QOS =  0;


int payment(std::string user_id,double amount){
  std::ofstream file("temp.txt");
  std::fstream myfile ("data.txt");
  std::string id;
  double balance;
  int flag = 0;
  if(myfile.is_open()) {
    while(1)
  {

    myfile >>id >> balance;
    if( myfile.eof() ) break;
    if (id.compare(user_id)==0){
      if(balance>=amount){
      flag = 1;
      
      balance-=amount;
    }
    }
    file<<id<<" "<<balance<<std::endl;
  }
 }

  myfile.close();
  file.close();
  rename("temp.txt","data.txt");
  if (flag == 1){
   return 1;
  }
  else{
    return 0;
  }

}

int scan(double amount){
  matrix_hal::NFC nfc;
    matrix_hal::NFCData nfc_data;
  std::cout << "[NFC]: NFC started!" << std::endl;
  int sucess = 0;
  auto past_time = std::chrono::system_clock::now();
  auto current_time = std::chrono::system_clock::now();
  std::chrono::duration<double> duration = (current_time-past_time);
  while(duration.count()<60){
    current_time = std::chrono::system_clock::now();
    duration = current_time-past_time;
    nfc.Activate();
    nfc.ReadInfo(&nfc_data.info);
    nfc.Deactivate();

    if (nfc_data.info.recently_updated) {

        std::cout << "[NFC] : " + nfc_data.info.ToString() << std::endl;
    
        std::string user_id = nfc_data.info.UIDToHex();

        sucess = payment(user_id, amount);
        
        break;
    }
    std::this_thread::sleep_for(std::chrono::microseconds(10000));

}
return sucess;
}


int main() {
    ////////////////////
    // INITIAL SETUP //
    //////////////////

    // Setting up HAL bus
    matrix_hal::MatrixIOBus bus;
    if (!bus.Init()) return false;



    // Setting up NFC
    

    initMqtt(ADDRESS,CLIENTID,TOPIC,QOS);
      int success = 0;
     while(1){
       if(msg>0){
        
         success = scan(msg);
         msg = 0;
         std::cout<<"[NFC] : success"<<success<<std::endl;
    
       std::string s = std::to_string(success);
      char const *suc = s.c_str(); 
   publishStatus(topic_pub_status,(char*)suc);
   }

     }
    return 0;
}

kiosk.py

Python
Main script
#!/usr/bin/env python2
# -*- coding: utf-8 -*-

from snipsTools import SnipsConfigParser
from hermes_python.hermes import Hermes, MqttOptions
import io
import sys
from threading import Thread
import json
import csv
import datetime
import paho.mqtt.client as mqtt_client

CONFIG_MENU = "menu.json"
CONFIG_ORDER = "orders.csv"
CURRENT_ORDER_ID = 001
CURRENT_CUSTOMER_ID = 001
USER_FILE = "user.json"



class order(object):
    def __init__(self,userid,orderid_):

        self.state = -1
        self.order = {}
        self.orderID = orderid_
        self.customerID = userid
        self.lastDialogue = ""
        self.orderCost = 0
        self.allergies = []
        self.instructions = []
        self.loaduserData()

    def loaduserData(self):
        try:
            self.allergies.append(kiosk.user[self.customerID]["allergies"])
        except:
            pass

    def repeatLastOrder(self):
        order_ = self.allergies.append(kiosk.user[self.customerID]["lastOrder"])
        dialogue = ""
        if order:
            self.order = order_
            dialogue = self.reciteOrder()
        else:
            dialogue = "I can't find your old order, but you can always make \
            a new one. "
    # mqtt callback after recieving payment status from nfc card reader.

    def payment_status_callback(self,msg):

        dialogue = ""
        if int(msg.payload) == 0:
            self.state = 8
            dialogue = " Sorry your order cannot be processed. "
            kiosk.mqtt.publish("everloop","3")
        elif int(msg.payload) ==1:
            dialogue = " Thank you for your order. "
            self.state = 7
            kiosk.mqtt.publish("everloop","3")

        self.lastDialogue = dialogue

    # generates text to be displayed on the GUI
    def guiText(self):
        cost = 0
        s="OrderID: " + str(self.orderID) + " " + "\n"
        for item,amount in self.order.items():
            s += str(amount) +"    x    " +  str(item) + "\n"
            cost += kiosk.menu[item] * amount

        s +=  str(cost) + "    ==    Total \n"
        s += "Allergies     : " + str(self.allergies) + "\n"
        s += "Instructions  : " + str(self.instructions) + "\n"
        return s

    # this function is called if face of this user is detected or
    def face_detection_callback(self,msg):

        dialogue = ""
        if self.state == 9:
            self.state = 10
        return dialogue

    def payment(self):
        kiosk.mqtt.publish("everloop","4")
        kiosk.mqtt.publish("payment/start",self.orderCost)

    def vending(self):
        pass


    def deliver(self):

        kiosk.mqtt.publish("motors",2)
        kiosk.mqtt.publish("motors",1)
        self.state = 11



    def checkForAllergies(self):
        dialogue = "I have noticed "
        count = 0
        for item in self.order.keys():
            for allergy in self.allergies:
                if allergy in kiosk.ingredients[item]:
                    dialogue = str(item) + " contain " + str(allergy)
                    count +=1
        if count >0:
            return dialogue
        else:
            return ""

    def calOrder(self):
        self.orderCost = 0
        for item,amount in self.order.items():
            self.orderCost += kiosk.menu[item] * amount

    def writeOrderFile(self):
        time_stamp = datetime.datetime.now()
        with open(CONFIG_ORDER, 'a') as f:
            for item,quantity in self.order.items():
                fields=[time_stamp,self.orderID,self.customerID,item,quantity]
                writer = csv.writer(f)
                writer.writerow(fields)

    def writeUserFile(self):
        if self.customerID in kiosk.user.keys():
            kiosk.user[self.customerID]["lastOrder"] = self.order
            kiosk.user[self.customerID]["allergies"] = self.allergies
        else:
            d = {"customerID": self.customerID, "lastOrder" : self.order,
             "allergies": self.allergies}
            kiosk.user[self.customerID] = d
        with open('user.json', 'w') as json_file:
            json.dump(kiosk.user, json_file)

    def orderCompleted(self):

        self.writeOrderFile()
        self.writeUserFile()





    def reciteOrder(self):
        dialogue = "Your order contains "
        for i in self.order.items():
            dialogue += str(i[1]) +" " +  str(i[0])
        return dialogue

    def finaliseOrder(self):
        dialogue = self.reciteOrder()
        self.calOrder()

        dialogue += ". Your order cost " + str(self.orderCost) \
        + " Please proceed to payment"

        return dialogue


    def addAllergies(self,intent_message):
        allergies_l= []

        for name,values in intent_message.slots.items():
            if name == "allergies":
                allergies_l = list(map(lambda x: str(x.value), values.all()))


        dialogue = ""
        for a in allergies_l:
            self.allergies.append(a)
            dialogue += " " + str(a)

        dialogue += " is added. "
        allergyAlert = self.checkForAllergies()
        if(allergyAlert):
            dialogue += allergyAlert
            self.state = 3

        else:
            self.state = 4

        return dialogue

    # -> action callbacks
    def addItems(self, intent_message):

        #print ("[Received] intent: {}".format(intent_message.intent.intent_name))
        for name,values in intent_message.slots.items():
            if name == "item":
                items = list(map(lambda x: str(x.value), values.all()))

            if name == "amount":
                amount = list(map(lambda x: int(x.value), values.all()))


        try:
            if len(items) == len(amount):
                add = {}
                add = dict(zip(items,amount))

                dialogue = ""

                for dish,amount in add.items():
                    if dish in self.order.keys():
                        self.order[dish] = self.order[dish] + amount
                    else:
                        if dish in kiosk.menu.keys():
                            self.order[dish] = amount
                            dialogue += str(amount) +" " +  str(dish)


                dialogue += " is added to your order. "


            else:
                dialogue = " Sorry, please use numbers for quantity. "




        except:
            dialogue =  " Sorry, I didn't get that. "

        self.state = 0;


        return dialogue



    def removeItems(self,intent_message):
        for name,values in intent_message.slots.items():
            if name == "item":
                items = list(map(lambda x: str(x.value), values.all()))

            if name == "amount":
                amount = list(map(lambda x: int(x.value), values.all()))
        p= []
        try:
            p = map(lambda x: self.order.pop(x,""),items)
        except:
            pass
        dialogue=""
        count=0
        for i in range(len(p)):
            if p[i]:
                count += 1
                dialogue+= " " + str(item[i]) + ", "
        if count == 1:
            dialogue+=" is removed from your order "
        if count  > 1:
            dialogue+=" are removed from your order "

        if count == 0:
            dialogue = " Nothing to remove, "

        self.state = 0

        return dialogue


    def suggestion(self,intent_message):
        pass
#        for name,values in intent_message.slots.items():
#            if name == "menuSection":
#                section_l = list(map(lambda x: str(x.value), values.all()))

 #       dialogue = ""

#        for section in section_l:
#            dialogue += "our top 3 items in" + section + "are" \
#            + suggestion_list[section][0] +" " + suggestion_list[section][1]\
#            + "and" + suggestion_list[section][2]

#        self.state = 0

#        return dialogue

    def removeAllergicItems(self):
        for item in self.order.keys():
            for allergy in self.allergies:
                if allergy in kiosk.ingredients[item]:
                    self.order.pop(item)

    def addInstructions(self,intent_message):
        instructions_l = []
        dialogue = ""
        for name,values in intent_message.slots.items():
            if name == "specialRequest":
                instructions_l = list(map(lambda x: str(x.value), values.all()))

        for i in instructions_l:
            self.instructions.append(i)
            dialogue += str(i)
        self.state = 6
        dialogue += "is added."

        return dialogue

    def response(self,intent_message):
        for name,values in intent_message.slots.items():
            if name == "response":
                response = list(map(lambda x: str(x.value), values.all()))
        dialogue = ""

        if self.state == 0:
            if "no" in response:
                self.state =  1

            else:
                self.state = 0
                dialogue = " Please specify your order in items and quantity "

        elif self.state == 1:
            if "no" in response:
                self.state = 4

            else:
                self.state = 2


        elif self.state == 3:
            self.state = 4
            if "yes" in response:
                self.removeAllergicItems()

        elif self.state == 4:
            if "yes" in response:
                self.state = 5
            else:
                self.state = 6

        return dialogue


    def order_intent_callback(self,hermes,intent_message):

        print ("[Received] intent: {}".format(intent_message.intent.intent_name))

        if intent_message.intent.intent_name == "verma-rishabh:addItems":
            self.lastDialogue = self.addItems(intent_message)

        if intent_message.intent.intent_name == "verma-rishabh:removeItems":
            self.lastDialogue = self.removeItems(intent_message)

        if intent_message.intent.intent_name == "verma-rishabh:suggestion":
            self.lastDialogue = self.suggestion(intent_message)

        if intent_message.intent.intent_name == "verma-rishabh:response":
            self.lastDialogue = self.response(intent_message)

        if intent_message.intent.intent_name == "verma-rishabh:allergies":
            self.lastDialogue = self.addAllergies(intent_message)

        if intent_message.intent.intent_name == "verma-rishabh:specialRequest":
            self.lastDialogue = self.addInstructions(intent_message)

        self.stateSpace(hermes,intent_message)

    def stateSpace(self,hermes,intent_message):
        kiosk.mqtt.publish("everloop","0")

        if self.state == 0:
            self.lastDialogue += " Would you like to edit your order or continue?"
            hermes.publish_continue_session(intent_message.session_id,\
            self.lastDialogue ,
            ["verma-rishabh:response","verma-rishabh:addItems",\
            "verma-rishabh:removeItems",\
            "verma-rishabh:suggestion"],"")
            kiosk.mqtt.publish("everloop","1")


        elif self.state == 1:
            self.lastDialogue += " Would you like to add any allergies?"
            hermes.publish_continue_session(intent_message.session_id,\
            self.lastDialogue ,\
            ["verma-rishabh:response","verma-rishabh:allergies"],"")
            kiosk.mqtt.publish("everloop","1")


        elif self.state == 2:
            self.lastDialogue += " Please state your allergies"
            hermes.publish_continue_session(intent_message.session_id,\
            self.lastDialogue ,\
            ["verma-rishabh:allergies"],"")
            kiosk.mqtt.publish("everloop","1")


        elif self.state == 3:
            self.lastDialogue += " Would you like to remove these items?"
            hermes.publish_continue_session(intent_message.session_id,\
            self.lastDialogue ,\
            ["verma-rishabh:response"],"")
            kiosk.mqtt.publish("everloop","1")

        elif self.state == 4:
            self.lastDialogue += " Would you like to add any instructions?"
            hermes.publish_continue_session(intent_message.session_id,\
            self.lastDialogue ,\
            ["verma-rishabh:specialRequest","verma-rishabh:response"],"")

        elif self.state == 5:
            self.lastDialogue += " Please state your instructions"
            hermes.publish_continue_session(intent_message.session_id,\
            self.lastDialogue ,\
            ["verma-rishabh:specialRequest"],"")
            kiosk.mqtt.publish("everloop","1")

        elif self.state == 6:
            self.lastDialogue = self.finaliseOrder()
            self.lastDialogue += " Please place your card near the reader"
            hermes.publish_end_session(intent_message.session_id,\
            self.lastDialogue)
            self.payment()
            kiosk.mqtt.publish("everloop","4")

        elif self.state == 7:
            self.lastDialogue += " Your orderid is " + str(self.orderID)
            hermes.publish_start_session_notification("default",\
            self.lastDialogue,"")
            kiosk.mqtt.publish("everloop","0")


            self.orderCompleted()
            text = self.guiText()
            kiosk.mqtt.publish("guiBack/text",text)

        elif self.state == 8:
            self.lastDialogue += ""
            hermes.publish_start_session_notification("default",\
            self.lastDialogue,"")
            kiosk.mqtt.publish("everloop","0")


        elif self.state == 9:

            self.lastDialogue = "Order number " + str(self.orderID) \
            + " please collect your order"

            hermes.publish_start_session_notification("default",\
            self.lastDialogue,"")
            kiosk.mqtt.publish("everloop","0")



        elif self.state == 10:
            print ("[Kiosk] : delivering Order")
            self.deliver()
#TODO for idle everloop

        text = self.guiText()
        kiosk.mqtt.publish("guiFront/text",text)

        #print (self.dialogue)

class kiosk(object):

    def on_connect(self,client, userdata, flags, rc):
        print('[Kiosk] : Connected')
        kiosk.mqtt.subscribe("payment/status")
        kiosk.mqtt.subscribe("camera/recognisedIds")
        kiosk.mqtt.subscribe("guiBack/completedOrder")


    def __init__(self):
        self.mqtt_addr = "raspberrypi.local:1883"
        kiosk.currentOrder=[]
        self.newFace = 0
        kiosk.menu = self.loadMenu()
        kiosk.ingredients = self.loadingredients()
        kiosk.user = self.loadUserFile()
        kiosk.mqtt = mqtt_client.Client()

        self.loadMqtt()
        self.start_blocking()



    def loadMqtt(self):

        kiosk.mqtt.on_connect = self.on_connect
        kiosk.mqtt.on_message = self.mqtt_callback
        kiosk.mqtt.connect('raspberrypi.local', 1883)
        kiosk.mqtt.loop_start()

    def loadMenu(self):
        menuDict = {}
        with open(CONFIG_MENU) as config_menu_file:
            menu=json.load(config_menu_file)
            for section in menu.values():

                map(lambda x,y: menuDict.update({x:y["price"]}),
                section[0].keys(),section[0].values())

        return menuDict


    def loadingredients(self):
        allergiesDict = {}
        with open(CONFIG_MENU) as config_allergies_file:
            menu=json.load(config_allergies_file)
            for section in menu.values():

                map(lambda x,y: allergiesDict.update({x:y["ingredients"]}),
                section[0].keys(),section[0].values())

        return allergiesDict


    def loadUserFile(self):
        with open(USER_FILE) as file:
            user=json.load(file)
        return user

    def newOrder(self):
        global CURRENT_ORDER_ID,CURRENT_CUSTOMER_ID
        if self.newFace != 0:
            userid = self.newFace
        else:
            userid = CURRENT_CUSTOMER_ID
            CURRENT_CUSTOMER_ID +=1
            print("adding new face ")
            kiosk.mqtt.publish("camera/addId",userid)

        kiosk.currentOrder.append(order(userid,CURRENT_ORDER_ID))
        CURRENT_ORDER_ID +=1

    def master_intent_callback(self, hermes, intent_message):
        #if latest order is already completed start new one
        if not kiosk.currentOrder:
            self.newOrder()
            kiosk.mqtt.publish("guiFront/text","")
            kiosk.currentOrder[-1].order_intent_callback(hermes, intent_message)

        elif kiosk.currentOrder[-1].state> 6:
            self.newOrder()
            kiosk.mqtt.publish("guiFront/text","")
            kiosk.currentOrder[-1].order_intent_callback(hermes, intent_message)

        else:
            kiosk.currentOrder[-1].order_intent_callback(hermes, intent_message)

# mqtt callbacks

    def mqtt_callback(self,client, userdata, msg):
        with Hermes() as hermes:

        #    print ("mqtt reciever" + msg.topic)

            if msg.topic == "payment/status":
                print("[payment status] : " + str (msg.payload))
                kiosk.currentOrder[-1].payment_status_callback(msg)
                kiosk.currentOrder[-1].stateSpace(hermes,msg)

            if msg.topic == "camera/recognisedIds":
                ids = list(map(int,msg.payload.split()))
                print ("[face detected] : " + str(ids))

                for user in kiosk.currentOrder:

                    if user.customerID in ids:
                        user.face_detection_callback(msg)
                        if user.state == 10:
                            user.stateSpace(hermes,msg)
                        ids.remove(user.customerID)
                # if new face, save it in self.newFace.
                if ids:
                    ids.sort()                                                  #makes sure we get non 0 id if present
                    self.newFace = ids[-1]


            if msg.topic == "guiBack/completedOrder":
                print("[Order Completed")
                for user in kiosk.currentOrder:
                    if user.orderID == int(msg.payload) and user.state == 7:
                        user.state = 9


                        user.stateSpace(hermes,msg)






# subscribing to snips intents
    def start_blocking(self):

        with Hermes(self.mqtt_addr) as h:
            h.subscribe_intents(self.master_intent_callback).start()


if __name__ == "__main__":

    kiosk()

everloop.cpp

C/C++
controls everloop
// System calls
#include <unistd.h>
// Input/output streams and functions
#include <iostream>
// Included for sin() function.
#include <cmath>

#include "mqtthelper.h"
// Interfaces with Everloop
#include "matrix_hal/everloop.h"
// Holds data for Everloop
#include "matrix_hal/everloop_image.h"
// Communicates with MATRIX device
#include "matrix_hal/matrixio_bus.h"

char ADDRESS[] = "localhost:1883";
char CLIENTID[] = "everloop";
char TOPIC[] = "everloop";
int QOS =  0;


float counter = 0;
// const float freq = 0.375;
const float freq = 0.375;





typedef struct {
    double r;       // a fraction between 0 and 1
    double g;       // a fraction between 0 and 1
    double b;       // a fraction between 0 and 1
} rgb;

typedef struct {
    double h;       // angle in degrees
    double s;       // a fraction between 0 and 1
    double v;       // a fraction between 0 and 1
} hsv;

hsv color_hsv;
rgb color_rgb;

hsv rgb2hsv(rgb in)
{
    hsv         out;
    double      min, max, delta;

    min = in.r < in.g ? in.r : in.g;
    min = min  < in.b ? min  : in.b;

    max = in.r > in.g ? in.r : in.g;
    max = max  > in.b ? max  : in.b;

    out.v = max;                                // v
    delta = max - min;
    if (delta < 0.00001)
    {
        out.s = 0;
        out.h = 0; // undefined, maybe nan?
        return out;
    }
    if( max > 0.0 ) { // NOTE: if Max is == 0, this divide would cause a crash
        out.s = (delta / max);                  // s
    }
    else {

             // if max is 0, then r = g = b = 0
        // s = 0, h is undefined
        out.s = 0.0;
        out.h = NAN;                            // its now undefined
        return out;
    }
    if( in.r >= max )                           // > is bogus, just keeps compilor happy
        out.h = ( in.g - in.b ) / delta;        // between yellow & magenta
    else
    if( in.g >= max )
        out.h = 2.0 + ( in.b - in.r ) / delta;  // between cyan & yellow
    else
        out.h = 4.0 + ( in.r - in.g ) / delta;  // between magenta & cyan

    out.h *= 60.0;                              // degrees

    if( out.h < 0.0 )
        out.h += 360.0;

    return out;
}


rgb hsv2rgb(hsv in)
{
    double      hh, p, q, t, ff;
    long        i;
    rgb         out;

    if(in.s <= 0.0) {       // < is bogus, just shuts up warnings
        out.r = in.v;
        out.g = in.v;
        out.b = in.v;
        return out;
    }
    hh = in.h;
    if(hh >= 360.0) hh = 0.0;
    hh /= 60.0;
    i = (long)hh;
    ff = hh - i;
    p = in.v * (1.0 - in.s);
    q = in.v * (1.0 - (in.s * ff));
    t = in.v * (1.0 - (in.s * (1.0 - ff)));

    switch(i) {
    case 0:
        out.r = in.v;
        out.g = t;
        out.b = p;
        break;
    case 1:
        out.r = q;
        out.g = in.v;
        out.b = p;
        break;
    case 2:
        out.r = p;
        out.g = in.v;
        out.b = t;
        break;

    case 3:
        out.r = p;
        out.g = q;
        out.b = in.v;
        break;
    case 4:
        out.r = t;
        out.g = p;
        out.b = in.v;
        break;
    case 5:
    default:
        out.r = in.v;
        out.g = p;
        out.b = q;
        break;
    }
    return out;
}






void pattern1(matrix_hal::EverloopImage everloop_image,matrix_hal::Everloop everloop)
{
  color_rgb.r = 15.0/255;
  color_rgb.g = 15.0/255;
  color_rgb.b = 125.0/255;
  color_hsv = rgb2hsv(color_rgb);

  for (int i = 0; i <=25; i++)
  {
    for (matrix_hal::LedValue &led : everloop_image.leds)
    {
      color_hsv.v = fmax(std::sin(freq*counter),0.05);
      color_rgb = hsv2rgb(color_hsv);
      led.red = (color_rgb.r*255.0);
      led.green = (color_rgb.g*255.0);
      led.blue = (color_rgb.b*255.0);
      counter = counter + 0.5;
    }
       everloop.Write(&everloop_image);
       if (i == 0) {
    // Output everloop status to console
    
    }
    // If i is cleanly divisible by 25
    //if ((i % 25) == 0) {
    //std::cout << "Time remaining (s) : " << 10 - (i / 25) << std::endl;
    //}
       usleep(40000);
  }


}
void pattern0(matrix_hal::EverloopImage everloop_image,matrix_hal::Everloop everloop)
{
  color_rgb.r = 15.0/255;
  color_rgb.g = 15.0/255;
  color_rgb.b = 125.0/255;
  color_hsv = rgb2hsv(color_rgb);
  for (int i = 0; i <=25; i++)
  {
    for (matrix_hal::LedValue &led : everloop_image.leds)
    {
      color_hsv.v = fmax(std::sin(freq),0.05);
      color_rgb = hsv2rgb(color_hsv);
      led.red = (color_rgb.r*255.0);
      led.green = (color_rgb.g*255.0);
      led.blue = (color_rgb.b*255.0);

    }
    everloop.Write(&everloop_image);
    usleep(40000);

  }
}
  
  void pattern2(matrix_hal::EverloopImage everloop_image,matrix_hal::Everloop everloop)
{

for (matrix_hal::LedValue &led : everloop_image.leds) {
    led.red = 0;
    // Set green to 100
    led.green = 100;
    led.blue = 0;
    led.white = 0;
}
    everloop.Write(&everloop_image);
    usleep(40000);
  
  

}


void pattern3(matrix_hal::EverloopImage everloop_image,matrix_hal::Everloop everloop)
{

for (matrix_hal::LedValue &led : everloop_image.leds) {
    led.red = 100;
    // Set green to 100
    led.green = 0;
    led.blue = 0;
    led.white = 0;
}
    everloop.Write(&everloop_image);
    usleep(40000);
  
  

}

void pattern4(matrix_hal::EverloopImage everloop_image,matrix_hal::Everloop everloop)
{

for (matrix_hal::LedValue &led : everloop_image.leds) {
    led.red = 50;
    // Set green to 100
    led.green = 50;
    led.blue = 0;
    led.white = 0;
}
    everloop.Write(&everloop_image);
    usleep(40000);
  
  

}

int main() {
  matrix_hal::MatrixIOBus bus;
  // Initialize bus and exit program if error occurs
  if (!bus.Init()) return false;

  int ledCount = bus.MatrixLeds();
  // Create EverloopImage object, with size of ledCount
  matrix_hal::EverloopImage everloop_image(ledCount);
  // Create Everloop object
  matrix_hal::Everloop everloop;
  // Set everloop to use MatrixIOBus bus
  everloop.Setup(&bus);

  initMqtt(ADDRESS,CLIENTID,TOPIC,QOS);

   while(1){
       //std::cout<<msg<<std::endl;
     if(msg==0){
       pattern0(everloop_image,everloop);
     }

     if(msg==1){
       pattern1(everloop_image,everloop);
     }
         if(msg==2){
       pattern2(everloop_image,everloop);
     }
          if(msg==3){
       pattern3(everloop_image,everloop);
     }
          if(msg==4){
       pattern4(everloop_image,everloop);
     }

   }


  return 0;
}

faceRecognition.py

Python
recognizes face
import cv2
import os
import paho.mqtt.client as mqtt
import numpy as np
from PIL import Image



# Global Variables
cam = cv2.VideoCapture(0)
detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml");
face_detected = 0
face_add = 0
face_id = 0

def on_connect(client, userdata, flags, rc):
    print("[faceRecognition]: Connected")
    client.subscribe("camera/addId")

# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
    global face_detected
    global face_add
    global face_id 
    #print(msg.topic+" "+str(msg.payload))
    

    if str(msg.topic) == "camera/addId":
        face_id = str(msg.payload)
        face_add = 1
def initMqtt():
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect("localhost", 1883)
    client.loop_start()
#loop_stop(force=False)

# function to get the images and label data
def getImagesAndLabels(path):

    imagePaths = [os.path.join(path,f) for f in os.listdir(path)]
    faceSamples=[]
    ids = []

    for imagePath in imagePaths:

        PIL_img = Image.open(imagePath).convert('L') # convert it to grayscale
        img_numpy = np.array(PIL_img,'uint8')

        id = int(os.path.split(imagePath)[-1].split(".")[1])
        faces = detector.detectMultiScale(img_numpy)

        for (x,y,w,h) in faces:
            faceSamples.append(img_numpy[y:y+h,x:x+w])
            ids.append(id)

    return faceSamples,ids


def trainer():
    path = 'dataset'

    recognizer = cv2.face.LBPHFaceRecognizer_create()



    print ("\n [FaceRecognition] Training faces. It will take a few seconds. Wait ...")
    faces,ids = getImagesAndLabels(path)
    recognizer.train(faces, np.array(ids))

    # Save the model into trainer/trainer.yml
    recognizer.write('trainer/trainer.yml') # recognizer.save() worked on Mac, but not on Pi

    # Print the numer of faces trained and end program
    #print("\n [FaceRecognition] {0} faces trained. Exiting Program".format(len(np.unique(ids))))


def faceAddition(face_id):
    face_detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
    # For each person, enter one numeric face id

    ## TODO: increament last id At last read last id from file

    #print("\n [FaceRecognition] Initializing face capture.")
    # Initialize individual sampling face count
    count = 0
    while(count<30):
        count += 1
        ret, img = cam.read()
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        faces = face_detector.detectMultiScale(gray, 1.3, 5)
        #cv2.imshow('image', img)
        for (x,y,w,h) in faces:

            cv2.rectangle(img, (x,y), (x+w,y+h), (255,0,0), 2)
            

            # Save the captured image into the datasets folder
            cv2.imwrite("dataset/User." + str(face_id) + '.' + str(count) + ".jpg", gray[y:y+h,x:x+w])
            print("[FaceRecognition]: Face capture count =   "  + str(count))
           # cv2.imshow('image', img)
        
        
        
       
        # Do a bit of cleanup
    
    trainer()

def faceDetection():
    global cam
    #print('[FaceRecognition]:  Face Detection ON')
    recognizer = cv2.face.LBPHFaceRecognizer_create()
    try:
        recognizer.read('trainer/trainer.yml')
    except:
        return [0]
    cascadePath = "haarcascade_frontalface_default.xml"
    faceCascade = cv2.CascadeClassifier(cascadePath);

    font = cv2.FONT_HERSHEY_SIMPLEX

    #iniciate id counter
    id = 0

    # Define min window size to be recognized as a face
    minW = 0.1*cam.get(3)
    minH = 0.1*cam.get(4)
    counter = 0
    recognised_ids = []
    while counter<=20:
        counter+=1
        ret, img =cam.read()
        gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

        faces = faceCascade.detectMultiScale(
            gray,
            scaleFactor = 1.2,
            minNeighbors = 5,
            minSize = (int(minW), int(minH)),
           )

        for(x,y,w,h) in faces:

            cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)

            id, confidence = recognizer.predict(gray[y:y+h,x:x+w])

            # Check if confidence is less them 100 ==> "0" is perfect match
            if (confidence < 100):
                pass
               # id = names[id]
                #print("[FaceRecognition]:  Face id detected = " str(id))
            #    confidence = "  {0}%".format(round(100 - confidence))
            else:
                id = 0
            #    confidence = "  {0}%".format(round(100 - confidence))
            # storing list of recognised/unrecognised faces
            if not id in recognised_ids:
                recognised_ids.append(id)
           # cv2.putText(img, str(id), (x+5,y-5), font, 1, (255,255,255), 2)
           # cv2.putText(img, str(confidence), (x+5,y+h-5), font, 1, (255,255,0), 1)


        
        #cv2.imshow('camera',img)
    #print('[FaceRecognitinon]:  detection completed')
    return recognised_ids


if __name__ == "__main__":
    client = mqtt.Client()
    initMqtt()
    
    cam.set(3, 640) # set video width
    cam.set(4, 480) # set video height
    face_detected = 1
    while(1):
        if face_detected == 1:
            
            list_id = faceDetection()
            print ("[FaceRecognitinon]: Detected face ids : " + str(list_id))
            str_id = ' '.join(map(str, list_id))
        
            client.publish("camera/recognisedIds",str_id)
        if face_add == 1:
            faceAddition(face_id) 
            face_add = 0
    
    usleep(10000);

Kitchen_gui.py

Python
kitchen gui
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import paho.mqtt.client as mqtt
from functools import partial

client = mqtt.Client()
count = 0




# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe("guiBack/text")



# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
        global count
        print(msg.topic+" "+str(msg.payload))
        s=str(msg.payload)
        label[count].setText((msg.payload))
        orderid = int(s.split(" ")[1])
        print orderid
        button[count].setText('Completed')
        head[count].setText(str(orderid))
        count +=1


def initMqtt():
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect("raspberrypi.local", 1883, 60)
    client.loop_start()

def clicked(i):
    client.publish("guiBack/completedOrder",str(head[i].text()))
    label[i].setText('')
    button[i].setText('')
    head[i].setText('')
def screen():
    vbox = QVBoxLayout()
    window = QWidget()
    h1 = QLabel('Cafe')
    h1.setStyleSheet("font: 30pt Comic Sans MS")
    h1.setAlignment(Qt.AlignCenter)
    vbox.addWidget(h1)
    vbox.addStretch()
    for i in range(5):
        vbox.addWidget(head[i])
        vbox.addStretch()
        vbox.addWidget(label[i])
        vbox.addStretch()
        vbox.addWidget(button[i])
        vbox.addStretch()

        head[i].setStyleSheet("font: 10pt Comic Sans MS")
        button[i].clicked.connect(partial(clicked,i))
        window.setLayout(vbox)
    window.setWindowTitle("Kitchen")
    window.setLayout(vbox)
    window.show()

    sys.exit(app.exec_())




if __name__ == '__main__':

   initMqtt()
   app = QApplication(sys.argv)
   label=[]
   button = []
   head = []
   for i in range(5):
       label.append(QLabel(""))
       button.append(QPushButton(""))
       head.append(QLabel(""))

   screen()

Menu.py

Python
Menu gui
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import paho.mqtt.client as mqtt

#import paho.mqtt.client as mqtt




def on_connect(client, userdata, flags, rc):
    print("[Menu]: Connected ")

    # Subscribing in on_connect() means that if we lose the connection and
    # reconnect then subscriptions will be renewed.
    client.subscribe("guiFront/text")

# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):

    l1.setText((msg.payload))
   # l1.repaint()
    
def initMqtt():
   client = mqtt.Client()
   client.on_connect = on_connect
   client.on_message = on_message
   client.connect("localhost", 1883, 60)
   client.loop_start()

def window():
   window = QWidget()
   hbox = QHBoxLayout()
   menu = QLabel()
   menu.setPixmap(QPixmap("menu.jpg"))
   hbox.addWidget(menu)
   hbox.addStretch()
   hbox.addWidget(l1)
   hbox.addStretch()
   window.setWindowTitle("MENU")
   window.setLayout(hbox)
   window.show()
   window.setLayout(hbox)
   sys.exit(app.exec_())



if __name__ == '__main__':
   initMqtt()
   app = QApplication(sys.argv)
   l1=QLabel()
   window()

motor.cpp

C/C++
controls motor
/*
 * GPIO servo output example
 */

/////////////////////////
// INCLUDE STATEMENTS //
///////////////////////

// System calls
#include <unistd.h>
// Input/output streams and functions
#include <iostream>
#include "mqtthelper.h"
// Interfaces with GPIO
#include "matrix_hal/gpio_control.h"
// Communicates with MATRIX device
#include "matrix_hal/matrixio_bus.h"

////////////////////////
// INITIAL VARIABLES //
//////////////////////

char ADDRESS[] = "localhost:1883";
char CLIENTID[] = "motors";
char TOPIC[] = "motors";
int QOS =  0;
// GPIOOutputMode is 1
const uint16_t GPIOOutputMode = 1;
// GPIOInputMode is 0
const uint16_t GPIOInputMode = 0;

// Holds desired GPIO pin for output [0-15]
uint16_t motor1_pin = 1;
// Holds desired output state
uint16_t motor2_pin = 2;
// Holds desired GPIO pin for input [0-15]



int main() {
    ////////////////////
    // INITIAL SETUP //
    //////////////////

    // Create MatrixIOBus object for hardware communication
    matrix_hal::MatrixIOBus bus;
    // Initialize bus and exit program if error occurs
    if (!bus.Init()) return false;

    /////////////////
    // MAIN SETUP //
    ///////////////

    // Create GPIOControl object
    matrix_hal::GPIOControl gpio;
    // Set gpio to use MatrixIOBus bus
    gpio.Setup(&bus);

    // Prompt user for GPIO pin

    // Set pin_out mode to output
    gpio.SetMode(motor1_pin, GPIOOutputMode);
    gpio.SetMode(motor2_pin, GPIOOutputMode);



    // Set pin_out to output pin_out_state
    gpio.SetGPIOValue(motor1_pin, 1);
    gpio.SetGPIOValue(motor2_pin, 1);


    initMqtt(ADDRESS,CLIENTID,TOPIC,QOS);
    // Endless loop
    while (true) {
      if (msg !=0){
        std::cout<<"[Vending Machine]: Running mortors";
        if (msg == 1){
            
            gpio.SetGPIOValue(motor1_pin, 0);
	    usleep(300000);
            gpio.SetGPIOValue(motor1_pin, 1);
            gpio.SetGPIOValue(motor2_pin, 0);
            usleep(1000000);
            gpio.SetGPIOValue(motor2_pin, 1); 

        
        }
        if (msg == 2){
            
            gpio.SetGPIOValue(motor1_pin, 0);
	    usleep(300000);
            gpio.SetGPIOValue(motor1_pin, 1);
            gpio.SetGPIOValue(motor2_pin, 0);
            usleep(1000000);
            gpio.SetGPIOValue(motor2_pin, 1);            
        }
        
        msg = 0;
      }


      // Sleep for 10000 microseconds
        usleep(10000);
    }

    return 0;
}

Voice activated vending machine

Credits

Rishabh Verma

Rishabh Verma

1 project • 3 followers
Electronics and Communication Engineer
Thanks to MJRoBot.

Comments