#!/usr/bin/perl -w use strict; use DBI; my $dock_status; my $this_rack_num = 1; # get initial dock status from db my $orig_dock_status = initialize_rack($this_rack_num); print "\n\norig_dock_status: $orig_dock_status\n\n"; #my $i = 0; # inifinitely scan the 1-wire bus while(1) { # get ids on the 1-wire net bus my $bus_ids = get_all_bus_ids(); # print "bus_ids: $bus_ids\n"; # if the dock has a vehicle in it if($bus_ids =~ /([A-Z0-9]{16})-([A-Z0-9]{16})-/) { #set the dock status to the vehicle_id $dock_status = $1; print "dock: $2 dock_status: $dock_status (vehicle_id)\n"; } # else if the dock is empty elsif($bus_ids =~ /([A-Z0-9]{16})-/) { # set the dock_status to empty $dock_status = "empty"; print "Dock is empty\n"; } # if a vehicle has been returned. ie: # if the original dock status has changed and the dock has a vehicle if(($orig_dock_status ne $dock_status) && ($dock_status ne "empty")) { #for right now the code only deals with one dock (1) my $dock_num = 1; print "vehicle returned. vehicle_id: $dock_status\n"; # update the orig_dock_status for comparison next time through the loop $orig_dock_status = $dock_status; # We've figured out $dock_status is a vehicle_id # now convert the long vehicle_id into a short friendly vehicle_num my $vehicle_num = convert_vehicle_id_to_num($dock_status); # Figure out who had the vehicle my $matched_user_id = match_user_to_vehicle($vehicle_num); my $full_name = match_user_id_to_user_name($matched_user_id); print "returned by: $full_name\n"; # Set vehicle.availability back to available update_vehicle_availability($vehicle_num, "available"); # update the dock.dock_status in the database to reflect the checked in vehicle # yikes... for right now dock is hard coded. update_dock_status($dock_num, $this_rack_num, $vehicle_num); # print "+++vehicle_num: $vehicle_num+++\n"; # Update events table: date_time, action, user_id, rack_id, dock_id, # vehicle_id #action, user_id, rack_num, dock_num, vehicle_num, [elapsed_time] add_events_entry("sign_in",$matched_user_id,$this_rack_num,$dock_num,$vehicle_num); # check if vehicle is overdue. If vehicle is overdue # Take appropriate action # haven't decided what this is yet, but if any action is going to be # taken it needs to be somewhat sophisiticated. For example, if # it's the first offense and the bike is only a few minutes late, # perhaps just send an email to the person urging them to return the # vehicle in a more timely manner. If it's a 3rd offense and the # vehicle is an hour late, send a charge to their account. There # needs to be a method for storing, retrieving, and weighing the # history of each individual. We could possible have "karma" # stored in the user database and as that number reaches certain # thresholds different actions are taken. Users could start at 0. # Certain infractions add predetermined number of points to their # karma. If they finally reach 100, for example, their account # would be set to disabled and they would no longer be able to use # the system. I think the Amsterdam program also rewarded people if # they brought vehicles from a heavily loaded rack to an empty rack. # Users could earn good karma for this and perhaps a very small # amount of karma could be earned if they return the vehicle quickly # to allow others to use the bikes # print " orig_dock_status: $dock_status\n\n"; } # if a vehicle has been checked out # check out code should already know about it elsif(($orig_dock_status ne $dock_status) && ($dock_status eq "empty")) { print "orig_dock_status: $orig_dock_status dock_status: $dock_status\n"; print "a bike has been removed from the dock\n"; # update the orig_dock_status for comparison next time through the loop $orig_dock_status = "empty"; } # if nothing has changed since the last time through else { # print "nothing changed "; # print "dock_status: $dock_status\n\n"; } `sleep 2`; # $i++; } #my @binky; #my $dock_id; #my $vehicle_id; #my %initial_rack_ids = initialize_rack(); #print "bla: $bus_ids"; #@binky = clean_rack_ids($bus_ids); #print "dock_id: $binky[1]\n"; #print "vehicle_id: $binky[0]\n"; #while (($dock_id,$vehicle_id) = each(%initial_rack_ids)) #{ # print "dock: $dock_id\nvehicle: $vehicle_id\n"; #} ################################################################################ # Function: get_all_bus_ids # Description: calls an external program which returns all ids on the 1-wire # net bus # Arguments: none # Returns: string raw ids (each id is separated by a - (there is a - at the # end as well) # Status: 80% (clean up. Also abstract the port to read from) ################################################################################ sub get_all_bus_ids { # get all the ids and store the raw string to $all_bus_ids # This assumes that the 1-wire net reader is connected to /dev/ttyS1 and # that get_ids is in the same directory that this program is being run from my $all_bus_ids = `./get_ids \/dev\/ttyS1`; return $all_bus_ids; } ################################################################################ # Function: clean_rack_ids # Description: takes the id dump for the bus and separates out into # vehicle_id/dock_id paired hash # Arguments: string raw_rack_ids # Returns: hash cleaned_rack_ids # Status: 5% ################################################################################ sub clean_rack_ids { my $raw_rack_ids = $_[0]; my @split_rack_ids; # remove the newline and the ending - chop $raw_rack_ids; chop $raw_rack_ids; @split_rack_ids = split /-/, $raw_rack_ids; #print "dock_id: $split_rack_ids[1]\n"; #print "vehicle_id: $split_rack_ids[0]\n"; return @split_rack_ids; } ################################################################################ # Function: initialize_rack() # Description: Before we get id's from the rack, the values need to be seeded # from the database. This function gets the status of each dock # from the dock table to get a values to be used for comparison # Arguments: int rack_id # Returns: hash - vehicle_id/dock_id pair? # Prerequisite: none # Status: 3% Need to figure out format of returned data and whole lot of other # stuff. Returned value is hard coded until I better understand what # is going on. ################################################################################ sub initialize_rack { my $rack_num = $_[0]; # temporary hack my $dock_num = 1; my %initial_rack_ids; # my %initial_rack_ids = ('9B000001A8CB4209','58000006377AD201'); my ($dsn) = "DBI:mysql:bike_program:localhost"; my ($user_name) = "bike"; my ($password) = "5xMts6"; my ($query); my ($dbh, $sth); my (@ary); # connect to database $dbh = DBI->connect ($dsn, $user_name, $password, { RaiseError => 1}); #build query - find dock_ids matching vehicle_ids # my $query = "SELECT dock\.dock_id, vehicle\.vehicle_id FROM dock, vehicle WHERE dock\.dock_status = vehicle\.vehicle_num AND dock\.rack_id='$rack_id'"; #this query only gets the status of rack 1 dock 1. This obviously needs major modifications $query = "SELECT dock_status FROM dock WHERE dock_num='1'"; # print $query; #execute query $sth = $dbh->prepare($query); $sth->execute(); #fetch results my $initial_dock_status = $sth->fetchrow_array(); # return %initial_rack_ids; return $initial_dock_status; } ################################################################################ # Function: convert_vehicle_id_to_num() # Description: converts long vehicle_id's to user friendly vehicle_num # Arguments: string vehicle_id # Returns: int vehicle_num # Prerequisite: none # Status: 5% ################################################################################ sub convert_vehicle_id_to_num { my $vehicle_id = $_[0]; my ($dsn) = "DBI:mysql:bike_program:localhost"; my ($user_name) = "bike"; my ($password) = "5xMts6"; my ($query); my ($dbh, $sth); my (@ary); # connect to database $dbh = DBI->connect ($dsn, $user_name, $password, { RaiseError => 1}); # create query $query = "SELECT vehicle_num FROM vehicle WHERE vehicle_id='$vehicle_id'"; # print $query; #execute query $sth = $dbh->prepare($query); $sth->execute(); #fetch results my $vehicle_num = $sth->fetchrow_array(); return $vehicle_num; } ################################################################################ # Function: match_user_to_vehicle # Description: checks the vehicle.availability field to get a user_id of the # person who has the vehicle # Arguments: string vehicle_id # Returns: int matched_user_id # Prerequisite: this function is intended to be used to check vehicles which # have their availability set to the user_id of the person who # has signed it out. # Status: 5% ################################################################################ sub match_user_to_vehicle { my $vehicle_num = $_[0]; my ($dsn) = "DBI:mysql:bike_program:localhost"; my ($user_name) = "bike"; my ($password) = "5xMts6"; my ($query); my ($dbh, $sth); my (@ary); # connect to database $dbh = DBI->connect ($dsn, $user_name, $password, { RaiseError => 1}); # create query $query = "SELECT availability FROM vehicle WHERE vehicle_num='$vehicle_num'"; # print $query; #execute query $sth = $dbh->prepare($query); $sth->execute(); #fetch results my $matched_user_id = $sth->fetchrow_array(); return $matched_user_id; } ################################################################################ # Function: match_user_id_to_user_name # Description: uses the user_id to get and return the users Name. # Arguments: string user_id # Returns: string full_name # Prerequisite: none # Status: 5% ################################################################################ sub match_user_id_to_user_name { my $user_id = $_[0]; my ($dsn) = "DBI:mysql:bike_program:localhost"; my ($user_name) = "bike"; my ($password) = "5xMts6"; my ($query); my ($dbh, $sth); my (@ary); # connect to database $dbh = DBI->connect ($dsn, $user_name, $password, { RaiseError => 1}); # create query $query = "SELECT first_name, last_name FROM user WHERE user_id='$user_id'"; # print $query; #execute query $sth = $dbh->prepare($query); $sth->execute(); #fetch results my @results = $sth->fetchrow_array(); my $full_name = $results[0] . " " . $results[1]; return $full_name; } ### NOTE: This function already exists in check out code ### ################################################################################ # Function: update_dock_status # Description: updates status of dock_status in the dock database # Arguments: int dock_num, int rack_num, string dock_status (empty or vehicle_id) # Returns: bool - true on success # Status: 90% (functional needs cleanup) ################################################################################ sub update_dock_status { my $dock_num = $_[0]; my $rack_num = $_[1]; my $dock_status = $_[2]; my $rows; my $outcome; my ($dsn) = "DBI:mysql:bike_program:localhost"; my ($user_name) = "bike"; my ($password) = "5xMts6"; my ($query); my ($dbh, $sth); my (@ary); # connect to database $dbh = DBI->connect ($dsn, $user_name, $password, { RaiseError => 1}); $query = "UPDATE dock SET dock_status='$dock_status' WHERE rack_num='$rack_num' AND dock_num='$dock_num'"; # print "\nquery: $query\n"; $rows = $dbh->do ($query); $dbh->disconnect(); if(!defined($rows)) #if there was an error { $outcome = "0"; #return false } elsif($rows == "0E0") #if no rows were affected { $outcome = "0"; # print "\ngot into the 0E0 Statement\n"; } else { $outcome = "1"; # return true } return $outcome; } ### NOTE: This function already exists in check out code ### ### I changed vehicle_id's to vehicle_num but not in check out code merge!!! ### ################################################################################ # Function: update_vehicle_availability # Description: updates availability of specified vehicle # Arguments: vehicle_id, availability (available, unavailable, or user_id) # Returns: bool - 1 on success, 0 on failure # Status: 90% (functional needs cleanup) ################################################################################ sub update_vehicle_availability { my $vehicle_num = $_[0]; my $availability = $_[1]; my $outcome; my $rows; my ($dsn) = "DBI:mysql:bike_program:localhost"; my ($user_name) = "bike"; my ($password) = "5xMts6"; my ($query); my ($dbh, $sth); my (@ary); # connect to database $dbh = DBI->connect ($dsn, $user_name, $password, { RaiseError => 1}); #build query $query = "UPDATE vehicle SET availability='$availability' WHERE vehicle_num='$vehicle_num'"; # print "\nupdate_vehicle_availability: $query\n"; #run query $rows = $dbh->do ($query); $dbh->disconnect(); # print "\nrows: $rows\n"; if(!defined($rows)) #if there was an error { $outcome = "0"; #return false # print "\nnot defined\n"; } elsif($rows == "0E0") #if no rows were affected { $outcome = "0"; # print "\ngot into the 0E0 Statement\n"; } else { $outcome = "1"; # return true } return $outcome; } ### NOTE: This function already exists in check out code ### ### I modified the sql statement since the time_interval is never used here ### have to generalize to check to see if the variable is present or not when ### building the statement ################################################################################ # Function: add_events_entry # Description: Gathers all the variables and makes an entry in the events table # Arguments: action, user_id, rack_num, dock_num, vehicle_num, [elapsed_time] # Returns: # Status: 75% (quasi-functional need to deal with the issue of optional arguments) ################################################################################ sub add_events_entry { #arguments my $action = $_[0]; my $user_id = $_[1]; my $rack_num = $_[2]; my $dock_num = $_[3]; my $vehicle_num = $_[4]; # my $time_interval = $_[5]; my $rows; my $outcome; my ($dsn) = "DBI:mysql:bike_program:localhost"; my ($user_name) = "bike"; my ($password) = "5xMts6"; my ($query); my ($dbh, $sth); my (@ary); # connect to database $dbh = DBI->connect ($dsn, $user_name, $password, { RaiseError => 1}); $query = "INSERT INTO events SET action='$action', user_id='$user_id', rack_num='$rack_num', dock_num='$dock_num', vehicle_num='$vehicle_num'"; # print "\nquery: $query\n"; $rows = $dbh->do ($query); $dbh->disconnect(); if(!defined($rows)) #if there was an error { $outcome = "0"; #return false } elsif($rows == "0E0") #if no rows were affected { $outcome = "0"; # print "\ngot into the 0E0 Statement\n"; } else { $outcome = "1"; # return true } return $outcome; }