Mohamed Hassan AbdulRahman
Created December 9, 2017

Hotel Control System

Saving Power is one of important topics nowadays. Saving power is needed everywhere but there is places needed it more

309

Things used in this project

Story

Read more

Schematics

Workflow

Code

people_counter.py

Python
from __future__ import print_function # WalabotAPI works on both Python 2 an 3.
from sys import platform
from os import system
from imp import load_source
from enum import Enum

import WalabotAPI as walabotAPI
walabotAPI.Init()

def PrintTrackerTargets(targets):
    system('cls' if platform == 'win32' else 'clear')
    if targets:
        for i, target in enumerate(targets):
            print(('y: {}'.format(target.yPosCm)))
    else:
        print('No Target Detected')


##################################################
#######   People Counter Class and Logic   #######
##################################################

#           ----------------------------
#  Outside |             |              |  Inside
#    The   |    Back     |    Front     |   the
#    Room  |             |              |   Room
#           ----------------------------

class Placement(Enum):
    Empty = 0  # Target not in the arena
    Back = 1  # Target in the back of the arena
    Front = 2  # Target in the front of the arena


class State(Enum):
    Idle = 0  # Nobody in the arena
    Bi = 1  # In the back - coming in
    Fi = 2  # In the front - coming in
    Bo = 3  # In the back - coming out
    Fo = 4  # In the front - coming out


def _get_placement(targets):
    if len(targets) is 0:
        return Placement.Empty
    if targets[0].yPosCm > 0:
        return Placement.Front
    if targets[0].yPosCm <= 0:
        return Placement.Back


class PeopleCounter:
    def __init__(self):
        self.placement = Placement.Empty
        self.state = State.Idle
        self.count = 0
        self.state_machine = {
            State.Idle:
                {Placement.Empty: State.Idle,
                 Placement.Back: State.Bi,
                 Placement.Front: State.Fo},
            State.Bi:
                {Placement.Empty: State.Idle,
                 Placement.Back: State.Bi,
                 Placement.Front: State.Fi},
            State.Fi:
                {Placement.Empty: State.Idle,  # increment
                 Placement.Back: State.Bi,
                 Placement.Front: State.Fi},
            State.Fo:
                {Placement.Empty: State.Idle,
                 Placement.Back: State.Bo,
                 Placement.Front: State.Fo},
            State.Bo:
                {Placement.Empty: State.Idle,  # increment
                 Placement.Back: State.Bo,
                 Placement.Front: State.Fo},
        }

    def update_state_get_count(self, targets):
        self.placement = _get_placement(targets)
        prev_state = self.state
        self.state = self.state_machine[self.state][self.placement]

        if prev_state == State.Bo and self.state == State.Idle:
            self._decrement()
        elif prev_state == State.Fi and self.state == State.Idle:
            self._increment()

        return self.count

    def _increment(self):
        self.count += 1
        return State.Idle

    def _decrement(self):
        self.count = max(self.count - 1, 0)
        return State.Idle


def PeopleCounterApp(roomNumber):
    # PeopleCounter object
    people_counter = PeopleCounter()
    # walabotAPI.SetArenaR - input parameters
    rArenaMin, rArenaMax, rArenaRes = 5, 120, 5
    # walabotAPI.SetArenaPhi - input parameters
    phiArenaMin, phiArenaMax, phiArenaRes = -60, 60, 3
    # walabotAPI.SetArenaTheta - input parameters
    thetaArenaMin, thetaArenaMax, thetaArenaRes = -20, 20, 10
    # Configure Walabot database install location (for windows)
    walabotAPI.SetSettingsFolder()
    # 1) Connect: Establish communication with walabot.
    walabotAPI.ConnectAny()
    # 2) Configure: Set scan profile and arena
    # Set Profile - to Tracker.
    walabotAPI.SetProfile(walabotAPI.PROF_TRACKER)
    # Set arena by Polar coordinates, with arena resolution
    walabotAPI.SetArenaR(rArenaMin, rArenaMax, rArenaRes)
    walabotAPI.SetArenaPhi(phiArenaMin, phiArenaMax, phiArenaRes)
    walabotAPI.SetArenaTheta(thetaArenaMin, thetaArenaMax, thetaArenaRes)
    # Walabot filtering MTI
    walabotAPI.SetDynamicImageFilter(walabotAPI.FILTER_TYPE_MTI)
    # 3) Start: Start the system in preparation for scanning.
    walabotAPI.Start()

    try:
        num_of_people = 0
        while True:
            # 4) Trigger: Scan (sense) according to profile and record signals
            # to be available for processing and retrieval.
            walabotAPI.Trigger()
            # 5) Get action: retrieve the last completed triggered recording
            targets = walabotAPI.GetTrackerTargets()
            # 6) Sort targets by amplitude
            targets = sorted(targets, key=lambda x: x.zPosCm, reverse=True)
            # 7) Update state and get people count
            prev_num_of_people = num_of_people
            num_of_people = people_counter.update_state_get_count(targets)
            if prev_num_of_people != num_of_people:
                print('# {} #\n'.format(num_of_people))
                # print y-axis of target found
                # PrintTrackerTargets(targets)
    except KeyboardInterrupt:
        pass
    finally:
        # 7) Stop and Disconnect.
        walabotAPI.Stop()
        walabotAPI.Disconnect()
        walabotAPI.Clean()
    print('Terminated successfully!')
    return num_of_people


if __name__ == '__main__':
    PeopleCounterApp(sys.argv[1])

   

get_room_number.py

Python
from flask import Flask
import sys
import subprocess

app = Flask(__name__)



@app.route('/<int:roomNumber>')
def roomNumber(roomNumber):
    return subprocess.check_output([sys.executable, "people_counter.py", roomNumber])


if __name__ == '__main__':
    app.run(debug=True)

Lambda Function

JavaScript
var AWS = require("aws-sdk");
const Alexa = require('alexa-sdk');
var request = require('request');

const APP_ID = "amzn1.ask.skill.xxxxxxxxxxx"
const urlRPi = "https://xxxxxxxxxx.ngrok.io";

const languageString = {
    'en': {
        'translation': {
            'ASK_FOR_ROOM': 'To check room status, please provide room number? ',
            'WRONG_ANSWER': 'Room number provided should be a number that is greater than zero. Please provide a room number?',
            'WRONG_HTML' : 'Something Wrong. Please try again later',
            'EMPTY_ROON': 'Room is Empty now',
            'NOT_EMPTY_ROOM': 'Room is not Empty now. There is %s objects moving inside the room',
            'STOP_MESSAGE': 'Ok, see you soon. Bye. ',
            'CANCEL_MESSAGE': 'Ok, see you soon. Bye. ',
            'START_UNHANDLED': 'Say restart to check another room.'
        }
    }
};

const SKILL_STATES = {
    START: '_STARTMODE', //Welcome & ask for room number.
    ANSWER_Q: '_ANSWERMODE',
};

exports.handler = (event, context, callback) => {
    try {

        //eventObj = event;
        const alexa = Alexa.handler(event, context);
        alexa.appId = APP_ID;

        // To enable string internationalization (i18n) features, set a resources object.
        alexa.resources = languageString;
        alexa.registerHandlers(newSessionHandlers, startStateHandlers, answerStateHandlers);
        alexa.execute();
    }
    catch (e) {
        context.fail("Exception: " + e);
    }
};

const newSessionHandlers = {
    'LaunchRequest': function () {
        console.log('Inside newSessionHandlers - LaunchRequest fn');
        this.handler.state = SKILL_STATES.START;
        this.emitWithState('StartConnection', true);
    },
    'NewSession': function () {
        console.log('Inside newSessionHandlers - LaunchRequest fn');
        this.handler.state = SKILL_STATES.START;
        this.emitWithState('StartConnection', true);
    },
    'AMAZON.StartOverIntent': function () {
        console.log('Inside newSessionHandlers - AMAZON.StartOverIntent fn');
        this.handler.state = SKILL_STATES.START;
        this.emitWithState('StartConnection', true);
    },
    'AMAZON.HelpIntent': function () {
        console.log('Inside newSessionHandlers - AMAZON.HelpIntent fn');
        this.handler.state = SKILL_STATES.HELP;
        this.emitWithState('helpTheUser', true);
    },
    'Unhandled': function () {
        console.log('Inside newSessionHandlers - Unhandled fn');
        const speechOutput = this.t('START_UNHANDLED');
        this.emit(':ask', speechOutput, speechOutput);
    },
};


const startStateHandlers = Alexa.CreateStateHandler(SKILL_STATES.START, {
    'StartConnection': function () {
        console.log('Inside startStateHandlers - StartConnection fn');

        var intent = this.event.request.intent;
        if (intent && intent.slots && intent.slots.room_number && intent.slots.room_number.value) {
            this.handler.state = SKILL_STATES.ANSWER_Q;
            this.emitWithState('RoomIntent', true);
        }
        else
        {
            let repromptText = this.t('ASK_FOR_ROOM');

            Object.assign(this.attributes, {
                'speechOutput': repromptText,
                'repromptText': repromptText
            });

            this.handler.state = SKILL_STATES.ANSWER_Q;
            this.emit(':ask', repromptText, repromptText);
        }
    },

    'Unhandled': function () {
        console.log('Inside newSessionHandlers - Unhandled fn');
        const speechOutput = this.t('START_UNHANDLED');
        this.emit(':ask', speechOutput, speechOutput);
    },
});



const answerStateHandlers = Alexa.CreateStateHandler(SKILL_STATES.ANSWER_Q, {

    'RoomIntent': function () {
        console.log('Inside insideStoryStateHandlers - AnswerIntent fn');
        var roomNumber = isRoomSlotValid(this.event.request.intent);
        console.log('roomNumber: ' + roomNumber);

        var speechOutput;

        if (roomNumber > 0){
            //Check the Ngrok
            var url = urlRPi + "//" + roomNumber;
            console.log('url: ' + url);

            request(url,
                (function (error, response, body) {
                    
                    this.handler.state = SKILL_STATES.ANSWER_Q;
                
                    var nofPersons = isBodyValid(body);
                    console.log('nofPersons:', nofPersons); 

                    if (nofPersons < 0) { //wrong OP
                        speechOutput = this.t('WRONG_HTML');
                    } else if (nofPersons > 0) { // room isn't empty
                        speechOutput = this.t('NOT_EMPTY_ROOM', nofPersons.toString());
                    }
                    else {//room is empty
                        speechOutput = this.t('EMPTY_ROOM');    
                    }

                    this.emit(':tell', speechOutput);
                }).bind(this)
            );

            
        }
        else {
            //error message
            speechOutput = this.t('WRONG_ANSWER');
            Object.assign(this.attributes, {
                'speechOutput': speechOutput,
                'repromptText': speechOutput
            });

            this.handler.state = SKILL_STATES.ANSWER_Q;
            this.emit(':ask', speechOutput, speechOutput);
        }
    },
    'AMAZON.StopIntent': function () {
        this.handler.state = GAME_STATES.SKILL_STATES.ANSWER_Q;
        const speechOutput = this.t('STOP_MESSAGE');

        //this.emit(':ask', speechOutput, speechOutput);
        this.emit(':tell', this.t('CANCEL_MESSAGE'));
    },
    'AMAZON.CancelIntent': function () {
        this.emit(':tell', this.t('CANCEL_MESSAGE'));
    },
    'AMAZON.RepeatIntent': function () {
        console.log('Inside insideStoryStateHandlers - AMAZON.RepeatIntent fn');

        this.handler.state = SKILL_STATES.START;
        this.emitWithState('StartConnection', true);

    },
    'AMAZON.HelpIntent': function () {
        console.log('Inside insideStoryStateHandlers - AMAZON.HelpIntent fn');

        var speechOutput = this.t('WRONG_ANSWER');
        Object.assign(this.attributes, {
            'speechOutput': speechOutput,
            'repromptText': speechOutput
        });

        this.handler.state = SKILL_STATES.ANSWER_Q;
        this.emit(':ask', speechOutput, speechOutput);
    },
    'Unhandled': function () {
        console.log('Inside insideStoryStateHandlers - Unhandled fn');

        this.handler.state = SKILL_STATES.START;
        this.emitWithState('StartConnection', true);
    },
    'SessionEndedRequest': function () {
        console.log('Inside insideStoryStateHandlers - SessionEndedRequest fn');
        console.log('Session ended state: ${this.event.request.reason}');
    },

});


function isRoomSlotValid(intent) {
    const answerSlotFilled = intent && intent.slots && intent.slots.room_number && intent.slots.room_number.value;
    const answerSlotIsInt = answerSlotFilled && !isNaN(parseInt(intent.slots.room_number.value, 10)) && (parseInt(intent.slots.room_number.value, 10) > 0) ;
    return answerSlotIsInt ? parseInt(intent.slots.room_number.value, 10) : -1 ;
}

function isBodyValid(body) {
    var nofObjects = parseInt(body, 10);  
    return isNaN(nofObjects) ? -1 : nofObjects ;
}

Credits

Mohamed Hassan AbdulRahman

Mohamed Hassan AbdulRahman

5 projects • 36 followers
Maker, aiming to make people’s life easier and more meaningful, using the latest HW & SW technologies, analysis and research.
Thanks to Walabot Tutorials and .

Comments