<commit_before>#!/usr/bin/env python
import time
import threading
import Queue
import os
import pyuarm
import rospy

from std_msgs.msg import String

def ros_try_catch(fn):
        def try_catch(*args, **kwargs):
            try:
                return fn(*args, **kwargs)
            except Exception as e:
                err_msg = "Error in function '" + fn.func_name + "': " + str(e.message)
                rospy.logerr(err_msg)
                rospy.signal_shutdown(err_msg)
        return try_catch

class UARM_interface():

    def __init__(self):
        self.uarm = None
        self.connected = False
        self.alive = True

        self.ros_rate = None
        self.ros_hz = 0

        self.settings = []

        self.uarm_read_thread = None
        self.uarm_read_queue = None
        self.read_queue_get_lock = threading.Lock()
        self.read_queue_put_lock = threading.Lock()
        self.uarm_read_pub = None

        self.uarm_interface_thread = None
        self.uarm_interface_queue = None
        self.interface_queue_get_lock = threading.Lock()
        self.interface_queue_put_lock = threading.Lock()

        self.playback_thread = None
        self.playback_active = False
        self.playback_data = []
        self.playback_rate = 1.0
        self.loading = False

        self.ja = []

    def get_setting(self, name, string_val=False):
        for line in self.settings:
            if line[0] == name:
                if string_val:
                    return line[1]
                else:
                    return float(line[1])

    def connect(self):
        try:
            self.uarm = pyuarm.get_uarm()
            self.connected = True
            self.load_parameters()
            self.start_threads()
            rospy.loginfo("Connected")
        except Exception as e:
            self.connected = False
            err = str(e.message)
            rospy.logerr("Connection error: " + err)
            rospy.signal_shutdown("Connection error")

    def shutdown(self):
        rospy.loginfo("Shutdown function call")
        rospy.signal_shutdown("Shutdown function call")
        start_shutdown = time.time()
        while self.uarm_interface_thread.is_alive() or self.uarm_read_thread.is_alive():
            # self.send_to_interface_queue("SHUTDOWN", priority=True)
            # self.send_to_read_queue("SHUTDOWN", priority=True)
            self.send_to_interface_queue("SHUTDOWN", priority=1)
            self.send_to_read_queue("SHUTDOWN", priority=1)

            if time.time()-start_shutdown > 5:
                break
        self.alive = False
        self.uarm.disconnect()

    def load_parameters(self):
        rospy.loginfo("Loading parameters")

        dir_path = os.path.dirname(os.path.realpath(__file__))
        f = open(dir_path + "/settings.txt")
        self.settings = []
        for line in f:
            self.settings.append(line.split(','))
        f.close()

        self.ros_hz = self.get_setting("ros_hz")

        self.uarm_read_pub = rospy.Publisher('uarm_read', String, queue_size=10)
        rospy.Subscriber("uarm_write", String, self.uarm_write_callback)
        rospy.init_node('uarm_node', anonymous=True)
        self.ros_rate = rospy.Rate(self.ros_hz)

        #self.uarm_read_queue = Queue.Queue()
        #self.uarm_interface_queue = Queue.Queue()

        self.uarm_read_queue = Queue.PriorityQueue()
        self.uarm_interface_queue = Queue.PriorityQueue()

        rospy.loginfo("Done loading parameters.")

    def start_threads(self):
        rospy.loginfo("Starting threads")
        if self.connected is True:
            self.uarm_read_thread = threading.Thread(target=self.uarm_read)
            self.uarm_interface_thread = threading.Thread(target=self.uarm_interface)

            self.uarm_read_thread.daemon = True
            self.uarm_read_thread.start()

            self.uarm_interface_thread.daemon = True
            self.uarm_interface_thread.start()

            self.request_detach()

        else:
            rospy.logerr("Startup error")
            rospy.signal_shutdown("Startup error")

    def uarm_interface(self):
        rospy.loginfo("uarm_interface running")
        while True and (rospy.is_shutdown() is False):
            request = self.get_from_interface_queue()
            print self.uarm_read_queue.qsize()
            if request == "READ":
                curr_vals = self.read_position()
                try:
                    self.send_to_read_queue(curr_vals)
                except Exception as e:
                    print "Error: ", e
                    rospy.logerr("Error writing to queue. Queue probably shutdown.")
                    break
                time.sleep(1.0/self.ros_hz)
                try:
                    self.ja = curr_vals[1]
                except Exception as e:
                    err = str(e.message)
                    rospy.logerr("uArm not ready! " + err)
                    rospy.signal_shutdown("Error reading from uArm")

                if self.playback_active is False and self.loading is False:
                    self.send_to_interface_queue("READ")

            elif request == "SHUTDOWN":
                break
            else:
                self.process_command(request)
                if self.playback_active is False and self.loading is False:
                    self.send_to_interface_queue("READ")

        rospy.loginfo("uarm_interface shutdown")
        self.shutdown()

    def request_detach(self):
        rospy.loginfo("uArm detach")
        self.send_to_interface_queue("DET")

    def request_attach(self):
        rospy.loginfo("uArm attach")
        self.send_to_interface_queue("ATT")

    def pump_on(self):
        rospy.loginfo("uArm Pump On")
        self.send_to_interface_queue("PUMP_ON")

    def pump_off(self):
        rospy.loginfo("uArm Pump Off")
        self.send_to_interface_queue("PUMP_OFF")

    @ros_try_catch
    def get_analog(self, pin_num):
        return round(self.uarm.get_analog(pin_num), 3)

    @ros_try_catch
    def get_joint_angles(self):
        return self.uarm.get_servo_angle()

    @ros_try_catch
    def read_position(self):
        return self.uarm.get_position()

    @ros_try_catch
    def read_joint_angles(self):
        # return [self.get_joint_angles(), time.time()]
        return self.get_joint_angles()

    def uarm_read(self):
        rospy.loginfo("uarm_read running")
        while True and (rospy.is_shutdown() is False):
            robot_values = self.get_from_read_queue(blocking=False)
            if robot_values == "SHUTDOWN":
                rospy.logwarn("sending shutdown signal")
                rospy.signal_shutdown("Normal Shutdown Procedure")
                break
            elif not robot_values:
                pass
            elif robot_values == "DONE":
                self.uarm_read_pub.publish("DONE")
            else:
                msg = str(robot_values)
                msg = msg.translate(None, '[]')
                self.uarm_read_pub.publish(msg)
                self.ros_rate.sleep()

        rospy.loginfo("uarm_read shutdown")

    def send_to_interface_queue(self, msg, msg_list=False, priority=10):
        with self.interface_queue_put_lock:
            if msg_list:
                for m in msg_list:
                    self.uarm_interface_queue.put((priority,m))
            else:
                self.uarm_interface_queue.put((priority, msg))

    # def send_to_interface_queue(self, msg, msg_list=False, priority=False):
    #     with self.interface_queue_put_lock:
    #         if msg_list:
    #             if priority:
    #                 msg_list = msg + self.get_from_interface_queue(all_msgs=True)
    #             for m in msg_list:
    #                 self.uarm_interface_queue.put(m)
    #         else:
    #             if priority:
    #                 msg_list = [msg] + self.get_from_interface_queue(all_msgs=True)
    #                 for m in msg_list:
    #                     self.uarm_interface_queue.put(m)
    #             else:
    #                 self.uarm_interface_queue.put(msg)

    def filter_interface_queue(self, msg_filter, invert=False):
        msgs = self.get_from_interface_queue(all_msgs=True, blocking=True)
        if msg_filter is not "":
            # print "FILTER: ", filter
            n = 0
            for i, msg in enumerate(msgs):
                if filter in msg and not invert:
                    msgs.pop(i)
                    n += 1
                elif filter not in msg and invert:
                    msgs.pop(i)
                    n += 1
            if msgs is not []:
                # print n, " messages filtered matching search terms", filter, invert
                # print msgs
                #self.send_to_interface_queue(msgs, msg_list=True, priority=True)
                self.send_to_interface_queue(msgs, msg_list=True, priority=1)

    def get_from_interface_queue(self, all_msgs=False, blocking=False):
        with self.interface_queue_get_lock:
            if all_msgs:
                msgs = []
                while self.uarm_interface_queue.qsize() > 0:
                    try:
                        msgs.append(self.uarm_interface_queue.get(blocking))

                    except Queue.Empty:
                        msgs = []

                return msgs
            else:
                try:
                    msg = self.uarm_interface_queue.get(blocking)
                except Queue.Empty:
                    msg = ""
                return msg

    def send_to_read_queue(self, msg, msg_list=False, priority=10):
        with self.read_queue_put_lock:
            if msg_list:
                for m in msg:
                    self.uarm_read_queue.put((priority,m))
            else:
                print msg
                self.uarm_read_queue.put((priority,msg))

    # def send_to_read_queue(self, msg, msg_list=False, priority=False):
    #     with self.read_queue_put_lock:
    #         if msg_list:
    #             if priority:
    #                 msg_list = msg + self.get_from_read_queue(all_msgs=True)
    #             for m in msg_list:
    #                 self.uarm_read_queue.put(m)
    #         else:
    #             if priority:
    #                 # print "Sending priority message, read_queue:", msg
    #                 msg_list = [msg] + self.get_from_read_queue(all_msgs=True)
    #                 for m in msg_list:
    #                     self.uarm_read_queue.put(m)
    #             else:
    #                 self.uarm_read_queue.put(msg)

    def get_from_read_queue(self, all_msgs=False, blocking=False):
        with self.read_queue_get_lock:
            if all_msgs:
                msgs = []
                while self.uarm_read_queue.qsize() > 0:
                    try:
                        msgs.append(self.uarm_read_queue.get(blocking))
                    except Queue.Empty:
                        msgs = []
                return msgs
            else:
                try:
                    msg = self.uarm_read_queue.get(blocking)
                except Queue.Empty:
                    msg = ""
                return msg

    def uarm_write_callback(self, data):
        # print "DATA: ", data.data
        if data.data == "CLEAR":
                self.get_from_interface_queue(all_msgs=True)
                self.get_from_read_queue(all_msgs=True)

        elif data.data[0] == "!":
                msg = data.data[1:]
                #print msg
                #self.send_to_interface_queue(msg, priority=True)
                self.send_to_interface_queue(msg, priority=1)
        else:
                self.send_to_interface_queue(data.data)

    def playback(self):
        if self.playback_data:
            self.loading = False
            self.get_from_interface_queue(all_msgs=True)  # flush queue
            try:
                joint_angles = self.ja
                self.send_to_interface_queue("JA"+str(joint_angles[0]) + "," +
                                             str(joint_angles[1]) + "," +
                                             str(joint_angles[2]) +
                                             str(joint_angles[3]))
            except Exception as e:
                # print "joint angles not ready yet: ", e
                err = str(e.message)
                rospy.logerr("joint angles not ready yet: " + err)
                rospy.signal_shutdown("joint angles not ready yet")

            self.send_to_interface_queue("ATT")

            self.filter_interface_queue("READ")

            for line in self.playback_data:
                # print self.playback_active, line
                if self.playback_active is False:
                    self.get_from_interface_queue(all_msgs=True)
                    break
                msg = str(line)

                self.send_to_interface_queue("READ")
                self.send_to_interface_queue(msg)

        self.send_to_interface_queue("BEEP")
        self.send_to_interface_queue("DET")
        self.playback_data = []

    def load_playback_data(self, data_line):
        self.loading = True
        rospy.loginfo("Loading playback data...")
        self.playback_data.append(data_line)

    @ros_try_catch
    def process_command(self, command):
        if command == "PUMP_ON":
            self.uarm.set_pump(1)

        if command == "PUMP_OFF":
            self.uarm.set_pump(0)

        if command == "ATT":
            self.uarm.set_servo_attach()

        if command == "DET":
            self.uarm.set_servo_detach()

        if command[0:3] == "POS" and self.playback_active:
            position = map(float, command[3:].split(','))
            self.uarm.set_position(position[0], position[1], position[2])

        if command[0:3] == "REL":
            adjust = float(command[3:])
            # print adjust
            self.uarm.set_position(x=0, y=0, z=adjust, speed=0, relative=True)

        if command[0:2] == "JA" and self.playback_active:
            angle = map(float, command[2:].split(','))
            for i in range(0, len(angle)-1):
                self.uarm.set_servo_angle(i, angle[i])

        if command[0:4] == "LOAD":
            self.load_playback_data(command[4:])

        if command == "PLAY":
            if self.playback_data:
                self.playback_active = True
                self.playback_thread = threading.Thread(target=self.playback)
                self.playback_thread.daemon = True

                self.playback_thread.start()
        if command == "BEEP":
            self.uarm.set_buzzer(10000, 0.1)
            #self.send_to_read_queue("DONE", priority=True)
            self.send_to_read_queue("DONE", priority=1)
            self.playback_active = False

        if command == "STOP":
            self.playback_active = False
            self.filter_interface_queue(msg_filter="READ")
            time.sleep(0.5)
            self.filter_interface_queue(msg_filter="JA")
            self.playback_data = []
<commit_msg>speed debug<commit_after>#!/usr/bin/env python
import time
import threading
import Queue
import os
import pyuarm
import rospy

from std_msgs.msg import String

def ros_try_catch(fn):
        def try_catch(*args, **kwargs):
            try:
                return fn(*args, **kwargs)
            except Exception as e:
                err_msg = "Error in function '" + fn.func_name + "': " + str(e.message)
                rospy.logerr(err_msg)
                rospy.signal_shutdown(err_msg)
        return try_catch

class UARM_interface():

    def __init__(self):
        self.uarm = None
        self.connected = False
        self.alive = True

        self.ros_rate = None
        self.ros_hz = 0

        self.settings = []

        self.uarm_read_thread = None
        self.uarm_read_queue = None
        self.read_queue_get_lock = threading.Lock()
        self.read_queue_put_lock = threading.Lock()
        self.uarm_read_pub = None

        self.uarm_interface_thread = None
        self.uarm_interface_queue = None
        self.interface_queue_get_lock = threading.Lock()
        self.interface_queue_put_lock = threading.Lock()

        self.playback_thread = None
        self.playback_active = False
        self.playback_data = []
        self.playback_rate = 1.0
        self.loading = False

        self.ja = []

    def get_setting(self, name, string_val=False):
        for line in self.settings:
            if line[0] == name:
                if string_val:
                    return line[1]
                else:
                    return float(line[1])

    def connect(self):
        try:
            self.uarm = pyuarm.get_uarm()
            self.connected = True
            self.load_parameters()
            self.start_threads()
            rospy.loginfo("Connected")
        except Exception as e:
            self.connected = False
            err = str(e.message)
            rospy.logerr("Connection error: " + err)
            rospy.signal_shutdown("Connection error")

    def shutdown(self):
        rospy.loginfo("Shutdown function call")
        rospy.signal_shutdown("Shutdown function call")
        start_shutdown = time.time()
        while self.uarm_interface_thread.is_alive() or self.uarm_read_thread.is_alive():
            # self.send_to_interface_queue("SHUTDOWN", priority=True)
            # self.send_to_read_queue("SHUTDOWN", priority=True)
            self.send_to_interface_queue("SHUTDOWN", priority=1)
            self.send_to_read_queue("SHUTDOWN", priority=1)
            time.sleep(0.5)
            if time.time()-start_shutdown > 5:
                break
        self.alive = False
        self.uarm.disconnect()

    def load_parameters(self):
        rospy.loginfo("Loading parameters")

        dir_path = os.path.dirname(os.path.realpath(__file__))
        f = open(dir_path + "/settings.txt")
        self.settings = []
        for line in f:
            self.settings.append(line.split(','))
        f.close()

        self.ros_hz = self.get_setting("ros_hz")

        self.uarm_read_pub = rospy.Publisher('uarm_read', String, queue_size=10)
        rospy.Subscriber("uarm_write", String, self.uarm_write_callback)
        rospy.init_node('uarm_node', anonymous=True)
        self.ros_rate = rospy.Rate(self.ros_hz)

        #self.uarm_read_queue = Queue.Queue()
        #self.uarm_interface_queue = Queue.Queue()

        self.uarm_read_queue = Queue.PriorityQueue()
        self.uarm_interface_queue = Queue.PriorityQueue()

        rospy.loginfo("Done loading parameters.")

    def start_threads(self):
        rospy.loginfo("Starting threads")
        if self.connected is True:
            self.uarm_read_thread = threading.Thread(target=self.uarm_read)
            self.uarm_interface_thread = threading.Thread(target=self.uarm_interface)

            self.uarm_read_thread.daemon = True
            self.uarm_read_thread.start()

            self.uarm_interface_thread.daemon = True
            self.uarm_interface_thread.start()

            self.request_detach()

        else:
            rospy.logerr("Startup error")
            rospy.signal_shutdown("Startup error")

    def uarm_interface(self):
        rospy.loginfo("uarm_interface running")
        while True and (rospy.is_shutdown() is False):
            request = self.get_from_interface_queue()
            print request
            if request == "READ":
                curr_vals = self.read_position()
                try:
                    self.send_to_read_queue(curr_vals)
                except Exception as e:
                    print "Error: ", e
                    rospy.logerr("Error writing to queue. Queue probably shutdown.")
                    break
                time.sleep(1.0/self.ros_hz)
                try:
                    self.ja = curr_vals[1]
                except Exception as e:
                    err = str(e.message)
                    rospy.logerr("uArm not ready! " + err)
                    rospy.signal_shutdown("Error reading from uArm")

                if self.playback_active is False and self.loading is False:
                    self.send_to_interface_queue("READ")

            elif request == "SHUTDOWN":
                break
            else:
                self.process_command(request)
                if self.playback_active is False and self.loading is False:
                    self.send_to_interface_queue("READ")

        rospy.loginfo("uarm_interface shutdown")
        self.shutdown()

    def request_detach(self):
        rospy.loginfo("uArm detach")
        self.send_to_interface_queue("DET")

    def request_attach(self):
        rospy.loginfo("uArm attach")
        self.send_to_interface_queue("ATT")

    def pump_on(self):
        rospy.loginfo("uArm Pump On")
        self.send_to_interface_queue("PUMP_ON")

    def pump_off(self):
        rospy.loginfo("uArm Pump Off")
        self.send_to_interface_queue("PUMP_OFF")

    @ros_try_catch
    def get_analog(self, pin_num):
        return round(self.uarm.get_analog(pin_num), 3)

    @ros_try_catch
    def get_joint_angles(self):
        return self.uarm.get_servo_angle()

    @ros_try_catch
    def read_position(self):
        return self.uarm.get_position()

    @ros_try_catch
    def read_joint_angles(self):
        # return [self.get_joint_angles(), time.time()]
        return self.get_joint_angles()

    def uarm_read(self):
        rospy.loginfo("uarm_read running")
        while True and (rospy.is_shutdown() is False):
            robot_values = self.get_from_read_queue(blocking=False)
            if robot_values == "SHUTDOWN":
                rospy.logwarn("sending shutdown signal")
                rospy.signal_shutdown("Normal Shutdown Procedure")
                break
            elif not robot_values:
                pass
            elif robot_values == "DONE":
                self.uarm_read_pub.publish("DONE")
            else:
                msg = str(robot_values)
                msg = msg.translate(None, '[]')
                self.uarm_read_pub.publish(msg)
                self.ros_rate.sleep()

        rospy.loginfo("uarm_read shutdown")

    def send_to_interface_queue(self, msg, msg_list=False, priority=10):
        with self.interface_queue_put_lock:
            if msg_list:
                for m in msg_list:
                    self.uarm_interface_queue.put((priority,m))
            else:
                self.uarm_interface_queue.put((priority, msg))

    # def send_to_interface_queue(self, msg, msg_list=False, priority=False):
    #     with self.interface_queue_put_lock:
    #         if msg_list:
    #             if priority:
    #                 msg_list = msg + self.get_from_interface_queue(all_msgs=True)
    #             for m in msg_list:
    #                 self.uarm_interface_queue.put(m)
    #         else:
    #             if priority:
    #                 msg_list = [msg] + self.get_from_interface_queue(all_msgs=True)
    #                 for m in msg_list:
    #                     self.uarm_interface_queue.put(m)
    #             else:
    #                 self.uarm_interface_queue.put(msg)

    def filter_interface_queue(self, msg_filter, invert=False):
        msgs = self.get_from_interface_queue(all_msgs=True, blocking=True)
        if msg_filter is not "":
            # print "FILTER: ", filter
            n = 0
            for i, msg in enumerate(msgs):
                if filter in msg and not invert:
                    msgs.pop(i)
                    n += 1
                elif filter not in msg and invert:
                    msgs.pop(i)
                    n += 1
            if msgs is not []:
                # print n, " messages filtered matching search terms", filter, invert
                # print msgs
                #self.send_to_interface_queue(msgs, msg_list=True, priority=True)
                self.send_to_interface_queue(msgs, msg_list=True, priority=1)

    def get_from_interface_queue(self, all_msgs=False, blocking=False):
        with self.interface_queue_get_lock:
            if all_msgs:
                msgs = []
                while self.uarm_interface_queue.qsize() > 0:
                    try:
                        msgs.append(self.uarm_interface_queue.get(blocking))

                    except Queue.Empty:
                        msgs = []

                return msgs
            else:
                try:
                    msg = self.uarm_interface_queue.get(blocking)
                except Queue.Empty:
                    msg = ""
                return msg

    def send_to_read_queue(self, msg, msg_list=False, priority=10):
        with self.read_queue_put_lock:
            if msg_list:
                for m in msg:
                    self.uarm_read_queue.put((priority,m))
            else:
                self.uarm_read_queue.put((priority,msg))

    # def send_to_read_queue(self, msg, msg_list=False, priority=False):
    #     with self.read_queue_put_lock:
    #         if msg_list:
    #             if priority:
    #                 msg_list = msg + self.get_from_read_queue(all_msgs=True)
    #             for m in msg_list:
    #                 self.uarm_read_queue.put(m)
    #         else:
    #             if priority:
    #                 # print "Sending priority message, read_queue:", msg
    #                 msg_list = [msg] + self.get_from_read_queue(all_msgs=True)
    #                 for m in msg_list:
    #                     self.uarm_read_queue.put(m)
    #             else:
    #                 self.uarm_read_queue.put(msg)

    def get_from_read_queue(self, all_msgs=False, blocking=False):
        with self.read_queue_get_lock:
            if all_msgs:
                msgs = []
                while self.uarm_read_queue.qsize() > 0:
                    try:
                        msgs.append(self.uarm_read_queue.get(blocking))
                    except Queue.Empty:
                        msgs = []
                return msgs
            else:
                try:
                    msg = self.uarm_read_queue.get(blocking)
                except Queue.Empty:
                    msg = ""
                return msg

    def uarm_write_callback(self, data):
        # print "DATA: ", data.data
        if data.data == "CLEAR":
                self.get_from_interface_queue(all_msgs=True)
                self.get_from_read_queue(all_msgs=True)

        elif data.data[0] == "!":
                msg = data.data[1:]
                #print msg
                #self.send_to_interface_queue(msg, priority=True)
                self.send_to_interface_queue(msg, priority=1)
        else:
                self.send_to_interface_queue(data.data)

    def playback(self):
        if self.playback_data:
            self.loading = False
            self.get_from_interface_queue(all_msgs=True)  # flush queue
            try:
                joint_angles = self.ja
                self.send_to_interface_queue("JA"+str(joint_angles[0]) + "," +
                                             str(joint_angles[1]) + "," +
                                             str(joint_angles[2]) +
                                             str(joint_angles[3]))
            except Exception as e:
                # print "joint angles not ready yet: ", e
                err = str(e.message)
                rospy.logerr("joint angles not ready yet: " + err)
                rospy.signal_shutdown("joint angles not ready yet")

            self.send_to_interface_queue("ATT")

            self.filter_interface_queue("READ")

            for line in self.playback_data:
                # print self.playback_active, line
                if self.playback_active is False:
                    self.get_from_interface_queue(all_msgs=True)
                    break
                msg = str(line)

                self.send_to_interface_queue("READ")
                self.send_to_interface_queue(msg)

        self.send_to_interface_queue("BEEP")
        self.send_to_interface_queue("DET")
        self.playback_data = []

    def load_playback_data(self, data_line):
        self.loading = True
        rospy.loginfo("Loading playback data...")
        self.playback_data.append(data_line)

    @ros_try_catch
    def process_command(self, command):
        if command == "PUMP_ON":
            self.uarm.set_pump(1)

        if command == "PUMP_OFF":
            self.uarm.set_pump(0)

        if command == "ATT":
            self.uarm.set_servo_attach()

        if command == "DET":
            self.uarm.set_servo_detach()

        if command[0:3] == "POS" and self.playback_active:
            position = map(float, command[3:].split(','))
            self.uarm.set_position(position[0], position[1], position[2])

        if command[0:3] == "REL":
            adjust = float(command[3:])
            # print adjust
            self.uarm.set_position(x=0, y=0, z=adjust, speed=0, relative=True)

        if command[0:2] == "JA" and self.playback_active:
            angle = map(float, command[2:].split(','))
            for i in range(0, len(angle)-1):
                self.uarm.set_servo_angle(i, angle[i])

        if command[0:4] == "LOAD":
            self.load_playback_data(command[4:])

        if command == "PLAY":
            if self.playback_data:
                self.playback_active = True
                self.playback_thread = threading.Thread(target=self.playback)
                self.playback_thread.daemon = True

                self.playback_thread.start()
        if command == "BEEP":
            self.uarm.set_buzzer(10000, 0.1)
            #self.send_to_read_queue("DONE", priority=True)
            self.send_to_read_queue("DONE", priority=1)
            self.playback_active = False

        if command == "STOP":
            self.playback_active = False
            self.filter_interface_queue(msg_filter="READ")
            time.sleep(0.5)
            self.filter_interface_queue(msg_filter="JA")
            self.playback_data = []
<|endoftext|>


<commit_before>from __future__ import unicode_literals

from django.contrib.sites.shortcuts import get_current_site
from django.contrib.syndication.views import Feed, add_domain
from django.utils import timezone
from django.utils.html import escape
from django.utils.feedgenerator import Rss201rev2Feed

from .models import Show, Episode, Enclosure
from .utils import EscapeFriendlyXMLGenerator
from . import settings

class ItunesFeed(Rss201rev2Feed):
    def write(self, outfile, encoding):
        """Method override to create self-closing elements.

        https://docs.djangoproject.com/en/1.10/ref/utils/#django.utils.feedgenerator.SyndicationFeed.write
        https://github.com/django/django/blob/master/django/utils/feedgenerator.py#L242
        """
        try:
            handler = EscapeFriendlyXMLGenerator(outfile, encoding, short_empty_elements=True)
        except TypeError:
            handler = EscapeFriendlyXMLGenerator(outfile, encoding)  # Python 2
        handler.startDocument()
        handler.startElement('rss', self.rss_attributes())
        handler.startElement('channel', self.root_attributes())
        self.add_root_elements(handler)
        self.write_items(handler)
        self.endChannelElement(handler)
        handler.endElement('rss')

    def rss_attributes(self):
        attrs = super(ItunesFeed, self).rss_attributes()
        attrs['xmlns:itunes'] = 'http://www.itunes.com/dtds/podcast-1.0.dtd'
        return attrs

    def add_root_elements(self, handler):
        super(ItunesFeed, self).add_root_elements(handler)
        handler.addQuickElement('copyright', self.feed['copyright'], escape=False, cdata=False)
        if self.feed['itunes']['subtitle']:
            handler.addQuickElement('itunes:subtitle', self.feed['itunes']['subtitle'], escape=False, cdata=True)
        if self.feed['itunes']['summary']:
            handler.addQuickElement('itunes:summary', self.feed['itunes']['summary'], escape=False, cdata=True)
        else:
            handler.addQuickElement('itunes:summary', self.feed['description'], escape=False, cdata=True)
        handler.addQuickElement('itunes:author', self.feed['itunes']['author']['name'])
        handler.startElement('itunes:owner', {})
        handler.addQuickElement('itunes:name', self.feed['itunes']['owner']['name'])
        handler.addQuickElement('itunes:email', self.feed['itunes']['owner']['email'])
        handler.endElement('itunes:owner')
        handler.addQuickElement('itunes:image', '', {'href': self.feed['itunes']['image']})
        for key, value in self.feed['itunes']['categories']:
            handler.startElement('itunes:category', {'text': key})
            for sub in value:
                handler.addQuickElement('itunes:category', '', {'text': sub})
            handler.endElement('itunes:category')
        handler.addQuickElement('itunes:explicit', self.feed['itunes']['explicit'])
        if self.feed['itunes']['block'] == 'yes':
            handler.addQuickElement('itunes:block', self.feed['itunes']['block'])
        if self.feed['itunes']['complete'] == 'yes':
            handler.addQuickElement('itunes:complete', self.feed['itunes']['complete'])

    def add_item_elements(self, handler, item):
        super(ItunesFeed, self).add_item_elements(handler, item)
        if item['itunes']['subtitle']:
            handler.addQuickElement('itunes:subtitle', item['itunes']['subtitle'], escape=False, cdata=True)
        if item['itunes']['summary']:
            handler.addQuickElement('itunes:summary', item['itunes']['summary'], escape=False, cdata=True)
        else:
            handler.addQuickElement('itunes:summary', item['description'], escape=False, cdata=True)
        if item['itunes']['author']['name']:
            handler.addQuickElement('itunes:author', item['itunes']['author']['name'])
        if item['itunes']['image']:
            handler.addQuickElement('itunes:image', '', {'href': item['itunes']['image']})
        handler.addQuickElement('itunes:explicit', item['itunes']['explicit'])
        if item['itunes']['block'] == 'yes':
            handler.addQuickElement('itunes:block', item['itunes']['block'])
        if item['itunes']['cc'] == 'yes':
            handler.addQuickElement('itunes:isClosedCaptioned', item['itunes']['cc'])
        if item['itunes']['duration']:
            handler.addQuickElement('itunes:duration', item['itunes']['duration'])

class ShowFeed(Feed):
    feed_type = ItunesFeed

    def get_object(self, request, *args, **kwargs):
        self.request = request
        if settings.PODCAST_SINGULAR:
            return Show.objects.get(id=settings.PODCAST_ID)
        else:
            return Show.objects.get(slug=kwargs['show_slug'])

    def title(self, obj):
        return '%s' % obj.title

    def link(self, obj):
        return obj.get_absolute_url()

    def description(self, obj):
        return '%s' % obj.description

    def feed_extra_kwargs(self, obj):
        copyright = escape('%s & %s %s %s') % ('℗', '©', timezone.now().year, escape(obj.copyright or obj.title))
        current_site = get_current_site(self.request)
        image_url = add_domain(current_site.domain, obj.get_image_url(), self.request.is_secure())
        return {
            'copyright': copyright,
            'itunes': {
                'subtitle': obj.subtitle,
                'summary': obj.summary,
                'author': {
                    'name': obj.author_name,
                    'email': obj.author_email,
                },
                'owner': {
                    'name': obj.owner_name or obj.author_name,
                    'email': obj.owner_email or obj.author_email,
                },
                'image': image_url,
                'categories': obj.get_categories_dict(),
                'explicit': obj.get_explicit(),
                'block': obj.get_block(),
                'complete': obj.get_complete(),
            }
        }

    def items(self, obj):
        return Episode.objects.filter(show=obj)[:50]

    def item_title(self, item):
        return '%s' % item.title

    def item_description(self, item):
        return '%s' % item.description

    def item_guid(self, item):
        return self.item_enclosure_url(item)

    def item_pubdate(self, item):
        return item.pub_date

    def item_categories(self, item):
        return tuple(category.full for category in item.show.categories.all())

    def item_enclosure_url(self, item):
        try:
            current_site = get_current_site(self.request)
            enclosure_url = Enclosure.objects.get(episode=item).file.url
            return add_domain(current_site.domain, enclosure_url, self.request.is_secure())
        except Enclosure.DoesNotExist:
            return None

    def item_enclosure_length(self, item):
        try:
            return Enclosure.objects.get(episode=item).file.size
        except Enclosure.DoesNotExist:
            return None

    def item_enclosure_mime_type(self, item):
        try:
            return Enclosure.objects.get(episode=item).type
        except Enclosure.DoesNotExist:
            return None

    def item_extra_kwargs(self, item):
        current_site = get_current_site(self.request)
        image_url = item.image.url if item.image else item.show.get_image_url()
        image = add_domain(current_site.domain, image_url, self.request.is_secure())
        try:
            enclosure = Enclosure.objects.get(episode=item)
            cc = enclosure.get_cc()
            duration = enclosure.get_duration()
        except Enclosure.DoesNotExist:
            cc = None
            duration = None
        return {
            'itunes': {
                'subtitle': item.subtitle,
                'summary': item.summary,
                'author': {
                    'name': item.get_author_name(),
                    'email': item.get_author_email(),
                },
                'image': image,
                'explicit': item.get_explicit(),
                'block': item.get_block(),
                'cc': cc,
                'duration': duration,
            }
        }
<commit_msg>Don't need item categories<commit_after>from __future__ import unicode_literals

from django.contrib.sites.shortcuts import get_current_site
from django.contrib.syndication.views import Feed, add_domain
from django.utils import timezone
from django.utils.html import escape
from django.utils.feedgenerator import Rss201rev2Feed

from .models import Show, Episode, Enclosure
from .utils import EscapeFriendlyXMLGenerator
from . import settings

class ItunesFeed(Rss201rev2Feed):
    def write(self, outfile, encoding):
        """Method override to create self-closing elements.

        https://docs.djangoproject.com/en/1.10/ref/utils/#django.utils.feedgenerator.SyndicationFeed.write
        https://github.com/django/django/blob/master/django/utils/feedgenerator.py#L242
        """
        try:
            handler = EscapeFriendlyXMLGenerator(outfile, encoding, short_empty_elements=True)
        except TypeError:
            handler = EscapeFriendlyXMLGenerator(outfile, encoding)  # Python 2
        handler.startDocument()
        handler.startElement('rss', self.rss_attributes())
        handler.startElement('channel', self.root_attributes())
        self.add_root_elements(handler)
        self.write_items(handler)
        self.endChannelElement(handler)
        handler.endElement('rss')

    def rss_attributes(self):
        attrs = super(ItunesFeed, self).rss_attributes()
        attrs['xmlns:itunes'] = 'http://www.itunes.com/dtds/podcast-1.0.dtd'
        return attrs

    def add_root_elements(self, handler):
        super(ItunesFeed, self).add_root_elements(handler)
        handler.addQuickElement('copyright', self.feed['copyright'], escape=False, cdata=False)
        if self.feed['itunes']['subtitle']:
            handler.addQuickElement('itunes:subtitle', self.feed['itunes']['subtitle'], escape=False, cdata=True)
        if self.feed['itunes']['summary']:
            handler.addQuickElement('itunes:summary', self.feed['itunes']['summary'], escape=False, cdata=True)
        else:
            handler.addQuickElement('itunes:summary', self.feed['description'], escape=False, cdata=True)
        handler.addQuickElement('itunes:author', self.feed['itunes']['author']['name'])
        handler.startElement('itunes:owner', {})
        handler.addQuickElement('itunes:name', self.feed['itunes']['owner']['name'])
        handler.addQuickElement('itunes:email', self.feed['itunes']['owner']['email'])
        handler.endElement('itunes:owner')
        handler.addQuickElement('itunes:image', '', {'href': self.feed['itunes']['image']})
        for key, value in self.feed['itunes']['categories']:
            handler.startElement('itunes:category', {'text': key})
            for sub in value:
                handler.addQuickElement('itunes:category', '', {'text': sub})
            handler.endElement('itunes:category')
        handler.addQuickElement('itunes:explicit', self.feed['itunes']['explicit'])
        if self.feed['itunes']['block'] == 'yes':
            handler.addQuickElement('itunes:block', self.feed['itunes']['block'])
        if self.feed['itunes']['complete'] == 'yes':
            handler.addQuickElement('itunes:complete', self.feed['itunes']['complete'])

    def add_item_elements(self, handler, item):
        super(ItunesFeed, self).add_item_elements(handler, item)
        if item['itunes']['subtitle']:
            handler.addQuickElement('itunes:subtitle', item['itunes']['subtitle'], escape=False, cdata=True)
        if item['itunes']['summary']:
            handler.addQuickElement('itunes:summary', item['itunes']['summary'], escape=False, cdata=True)
        else:
            handler.addQuickElement('itunes:summary', item['description'], escape=False, cdata=True)
        if item['itunes']['author']['name']:
            handler.addQuickElement('itunes:author', item['itunes']['author']['name'])
        if item['itunes']['image']:
            handler.addQuickElement('itunes:image', '', {'href': item['itunes']['image']})
        handler.addQuickElement('itunes:explicit', item['itunes']['explicit'])
        if item['itunes']['block'] == 'yes':
            handler.addQuickElement('itunes:block', item['itunes']['block'])
        if item['itunes']['cc'] == 'yes':
            handler.addQuickElement('itunes:isClosedCaptioned', item['itunes']['cc'])
        if item['itunes']['duration']:
            handler.addQuickElement('itunes:duration', item['itunes']['duration'])

class ShowFeed(Feed):
    feed_type = ItunesFeed

    def get_object(self, request, *args, **kwargs):
        self.request = request
        if settings.PODCAST_SINGULAR:
            return Show.objects.get(id=settings.PODCAST_ID)
        else:
            return Show.objects.get(slug=kwargs['show_slug'])

    def title(self, obj):
        return '%s' % obj.title

    def link(self, obj):
        return obj.get_absolute_url()

    def description(self, obj):
        return '%s' % obj.description

    def feed_extra_kwargs(self, obj):
        copyright = escape('%s & %s %s %s') % ('℗', '©', timezone.now().year, escape(obj.copyright or obj.title))
        current_site = get_current_site(self.request)
        image_url = add_domain(current_site.domain, obj.get_image_url(), self.request.is_secure())
        return {
            'copyright': copyright,
            'itunes': {
                'subtitle': obj.subtitle,
                'summary': obj.summary,
                'author': {
                    'name': obj.author_name,
                    'email': obj.author_email,
                },
                'owner': {
                    'name': obj.owner_name or obj.author_name,
                    'email': obj.owner_email or obj.author_email,
                },
                'image': image_url,
                'categories': obj.get_categories_dict(),
                'explicit': obj.get_explicit(),
                'block': obj.get_block(),
                'complete': obj.get_complete(),
            }
        }

    def items(self, obj):
        return Episode.objects.filter(show=obj)[:50]

    def item_title(self, item):
        return '%s' % item.title

    def item_description(self, item):
        return '%s' % item.description

    def item_guid(self, item):
        return self.item_enclosure_url(item)

    def item_pubdate(self, item):
        return item.pub_date

    def item_enclosure_url(self, item):
        try:
            current_site = get_current_site(self.request)
            enclosure_url = Enclosure.objects.get(episode=item).file.url
            return add_domain(current_site.domain, enclosure_url, self.request.is_secure())
        except Enclosure.DoesNotExist:
            return None

    def item_enclosure_length(self, item):
        try:
            return Enclosure.objects.get(episode=item).file.size
        except Enclosure.DoesNotExist:
            return None

    def item_enclosure_mime_type(self, item):
        try:
            return Enclosure.objects.get(episode=item).type
        except Enclosure.DoesNotExist:
            return None

    def item_extra_kwargs(self, item):
        current_site = get_current_site(self.request)
        image_url = item.image.url if item.image else item.show.get_image_url()
        image = add_domain(current_site.domain, image_url, self.request.is_secure())
        try:
            enclosure = Enclosure.objects.get(episode=item)
            cc = enclosure.get_cc()
            duration = enclosure.get_duration()
        except Enclosure.DoesNotExist:
            cc = None
            duration = None
        return {
            'itunes': {
                'subtitle': item.subtitle,
                'summary': item.summary,
                'author': {
                    'name': item.get_author_name(),
                    'email': item.get_author_email(),
                },
                'image': image,
                'explicit': item.get_explicit(),
                'block': item.get_block(),
                'cc': cc,
                'duration': duration,
            }
        }
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

"""
A simple library for managing the availability of ports.
"""

from __future__ import print_function

import time
import socket
import datetime
import argparse
import sys

from jaraco import timing
from py26compat import total_seconds

def client_host(server_host):
	"""Return the host on which a client can connect to the given listener."""
	if server_host == '0.0.0.0':
		# 0.0.0.0 is INADDR_ANY, which should answer on localhost.
		return '127.0.0.1'
	if server_host in ('::', '::0', '::0.0.0.0'):
		# :: is IN6ADDR_ANY, which should answer on localhost.
		# ::0 and ::0.0.0.0 are non-canonical but common
		# ways to write IN6ADDR_ANY.
		return '::1'
	return server_host

def _check_port(host, port, timeout=1.0):
	"""
	Raise an error if the given port is not free on the given host.

	>>> free_port = find_available_local_port()
	>>> _check_port('localhost', free_port)
	>>> _check_port('127.0.0.1', free_port)
	>>> _check_port('::1', free_port)
	"""
	if not host:
		raise ValueError("Host values of '' or None are not allowed.")
	host = client_host(host)
	port = int(port)

	# AF_INET or AF_INET6 socket
	# Get the correct address family for host (allows IPv6 addresses)
	try:
		info = socket.getaddrinfo(host, port, socket.AF_UNSPEC,
			socket.SOCK_STREAM)
	except socket.gaierror:
		if ':' in host:
			family = socket.AF_INET6
			addr = host, port, 0, 0
		else:
			family = socket.AF_INET
			addr = host, port
		item = family, socket.SOCK_STREAM, 0, "", addr
		info = [item]

	for res in info:
		af, socktype, proto, canonname, sa = res
		s = None
		try:
			s = socket.socket(af, socktype, proto)
			# important that a small timeout is set here to allow the check
			#  to fail fast.
			s.settimeout(timeout)
			s.connect((host, port))
			s.close()
		except socket.error:
			if s:
				s.close()
		else:
			tmpl = "Port {port} is in use on {host}."
			raise IOError(tmpl.format(**locals()))

class Timeout(IOError):
	pass

def free(host, port, timeout=float('Inf')):
	"""
	Wait for the specified port to become free (dropping or rejecting
	requests). Return when the port is free or raise a Timeout if timeout has
	elapsed.

	Timeout may be specified in seconds or as a timedelta.
	If timeout is None or ∞, the routine will run indefinitely.

	>>> free('localhost', find_available_local_port())
	"""
	if not host:
		raise ValueError("Host values of '' or None are not allowed.")

	if isinstance(timeout, datetime.timedelta):
		timeout = timeout.total_seconds()

	if timeout is None:
		# treat None as infinite timeout
		timeout = float('Inf')

	watch = timing.Stopwatch()

	while total_seconds(watch.split()) < timeout:
		try:
			# Expect a free port, so use a small timeout
			_check_port(host, port, timeout=0.1)
			return
		except IOError:
			# Politely wait.
			time.sleep(0.1)

	raise Timeout("Port {port} not free on {host}.".format(**locals()))
wait_for_free_port = free

def occupied(host, port, timeout=float('Inf')):
	"""
	Wait for the specified port to become occupied (accepting requests).
	Return when the port is occupied or raise a Timeout if timeout has
	elapsed.

	Timeout may be specified in seconds or as a timedelta.
	If timeout is None or ∞, the routine will run indefinitely.

	>>> occupied('localhost', find_available_local_port(), .1) # doctest: +IGNORE_EXCEPTION_DETAIL
	Traceback (most recent call last):
	    ...
	Timeout: Port ... not bound on localhost.
	"""
	if not host:
		raise ValueError("Host values of '' or None are not allowed.")

	if isinstance(timeout, datetime.timedelta):
		timeout = timeout.total_seconds()

	if timeout is None:
		# treat None as infinite timeout
		timeout = float('Inf')

	watch = timing.Stopwatch()

	while total_seconds(watch.split()) < timeout:
		try:
			_check_port(host, port, timeout=.5)
			# Politely wait
			time.sleep(0.1)
		except IOError:
			# port is occupied
			return

	raise Timeout("Port {port} not bound on {host}.".format(**locals()))
wait_for_occupied_port = occupied

def find_available_local_port():
	"""
	Find a free port on localhost.

	>>> 0 < find_available_local_port() < 65536
	True
	"""
	sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
	addr = '', 0
	sock.bind(addr)
	addr, port = sock.getsockname()[:2]
	sock.close()
	return port

class HostPort(str):
	"""
	A simple representation of a host/port pair as a string

	>>> hp = HostPort('localhost:32768')

	>>> hp.host
	'localhost'

	>>> hp.port
	32768

	>>> len(hp)
	15
	"""

	@property
	def host(self):
		host, sep, port = self.partition(':')
		return host

	@property
	def port(self):
		host, sep, port = self.partition(':')
		return int(port)

def _main():
	parser = argparse.ArgumentParser()
	global_lookup = lambda key: globals()[key]
	parser.add_argument('target', metavar='host:port', type=HostPort)
	parser.add_argument('func', metavar='state', type=global_lookup)
	parser.add_argument('-t', '--timeout', default=None, type=float)
	args = parser.parse_args()
	try:
		args.func(args.target.host, args.target.port, timeout=args.timeout)
	except Timeout as timeout:
		print(timeout, file=sys.stderr)
		raise SystemExit(1)

if __name__ == '__main__':
	_main()
<commit_msg>Don't cast to int<commit_after># -*- coding: utf-8 -*-

"""
A simple library for managing the availability of ports.
"""

from __future__ import print_function

import time
import socket
import datetime
import argparse
import sys

from jaraco import timing
from py26compat import total_seconds

def client_host(server_host):
	"""Return the host on which a client can connect to the given listener."""
	if server_host == '0.0.0.0':
		# 0.0.0.0 is INADDR_ANY, which should answer on localhost.
		return '127.0.0.1'
	if server_host in ('::', '::0', '::0.0.0.0'):
		# :: is IN6ADDR_ANY, which should answer on localhost.
		# ::0 and ::0.0.0.0 are non-canonical but common
		# ways to write IN6ADDR_ANY.
		return '::1'
	return server_host

def _check_port(host, port, timeout=1.0):
	"""
	Raise an error if the given port is not free on the given host.

	>>> free_port = find_available_local_port()
	>>> _check_port('localhost', free_port)
	>>> _check_port('127.0.0.1', free_port)
	>>> _check_port('::1', free_port)
	"""
	if not host:
		raise ValueError("Host values of '' or None are not allowed.")
	host = client_host(host)

	# AF_INET or AF_INET6 socket
	# Get the correct address family for host (allows IPv6 addresses)
	try:
		info = socket.getaddrinfo(host, port, socket.AF_UNSPEC,
			socket.SOCK_STREAM)
	except socket.gaierror:
		if ':' in host:
			family = socket.AF_INET6
			addr = host, port, 0, 0
		else:
			family = socket.AF_INET
			addr = host, port
		item = family, socket.SOCK_STREAM, 0, "", addr
		info = [item]

	for res in info:
		af, socktype, proto, canonname, sa = res
		s = None
		try:
			s = socket.socket(af, socktype, proto)
			# important that a small timeout is set here to allow the check
			#  to fail fast.
			s.settimeout(timeout)
			s.connect((host, port))
			s.close()
		except socket.error:
			if s:
				s.close()
		else:
			tmpl = "Port {port} is in use on {host}."
			raise IOError(tmpl.format(**locals()))

class Timeout(IOError):
	pass

def free(host, port, timeout=float('Inf')):
	"""
	Wait for the specified port to become free (dropping or rejecting
	requests). Return when the port is free or raise a Timeout if timeout has
	elapsed.

	Timeout may be specified in seconds or as a timedelta.
	If timeout is None or ∞, the routine will run indefinitely.

	>>> free('localhost', find_available_local_port())
	"""
	if not host:
		raise ValueError("Host values of '' or None are not allowed.")

	if isinstance(timeout, datetime.timedelta):
		timeout = timeout.total_seconds()

	if timeout is None:
		# treat None as infinite timeout
		timeout = float('Inf')

	watch = timing.Stopwatch()

	while total_seconds(watch.split()) < timeout:
		try:
			# Expect a free port, so use a small timeout
			_check_port(host, port, timeout=0.1)
			return
		except IOError:
			# Politely wait.
			time.sleep(0.1)

	raise Timeout("Port {port} not free on {host}.".format(**locals()))
wait_for_free_port = free

def occupied(host, port, timeout=float('Inf')):
	"""
	Wait for the specified port to become occupied (accepting requests).
	Return when the port is occupied or raise a Timeout if timeout has
	elapsed.

	Timeout may be specified in seconds or as a timedelta.
	If timeout is None or ∞, the routine will run indefinitely.

	>>> occupied('localhost', find_available_local_port(), .1) # doctest: +IGNORE_EXCEPTION_DETAIL
	Traceback (most recent call last):
	    ...
	Timeout: Port ... not bound on localhost.
	"""
	if not host:
		raise ValueError("Host values of '' or None are not allowed.")

	if isinstance(timeout, datetime.timedelta):
		timeout = timeout.total_seconds()

	if timeout is None:
		# treat None as infinite timeout
		timeout = float('Inf')

	watch = timing.Stopwatch()

	while total_seconds(watch.split()) < timeout:
		try:
			_check_port(host, port, timeout=.5)
			# Politely wait
			time.sleep(0.1)
		except IOError:
			# port is occupied
			return

	raise Timeout("Port {port} not bound on {host}.".format(**locals()))
wait_for_occupied_port = occupied

def find_available_local_port():
	"""
	Find a free port on localhost.

	>>> 0 < find_available_local_port() < 65536
	True
	"""
	sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
	addr = '', 0
	sock.bind(addr)
	addr, port = sock.getsockname()[:2]
	sock.close()
	return port

class HostPort(str):
	"""
	A simple representation of a host/port pair as a string

	>>> hp = HostPort('localhost:32768')

	>>> hp.host
	'localhost'

	>>> hp.port
	32768

	>>> len(hp)
	15
	"""

	@property
	def host(self):
		host, sep, port = self.partition(':')
		return host

	@property
	def port(self):
		host, sep, port = self.partition(':')
		return int(port)

def _main():
	parser = argparse.ArgumentParser()
	global_lookup = lambda key: globals()[key]
	parser.add_argument('target', metavar='host:port', type=HostPort)
	parser.add_argument('func', metavar='state', type=global_lookup)
	parser.add_argument('-t', '--timeout', default=None, type=float)
	args = parser.parse_args()
	try:
		args.func(args.target.host, args.target.port, timeout=args.timeout)
	except Timeout as timeout:
		print(timeout, file=sys.stderr)
		raise SystemExit(1)

if __name__ == '__main__':
	_main()
<|endoftext|>


<commit_before>'''
Created on 24 Jan 2017
@author: muth
'''
import os
import RPi.GPIO as GPIO
import threading
from Adafruit_Thermal import *
from time import sleep
from PIL import Image
from PIL import ImageOps
from PIL import ImageEnhance
from PIL import ImageDraw
from PIL import ImageFont
from smemlcd import SMemLCD
from picamera import PiCamera
from io import BytesIO

# Constants
S_WIDTH = 400
S_HEIGHT = 240
S_SIZE = (S_WIDTH, S_HEIGHT)
P_WIDTH = 640
P_HEIGHT = 384
P_SIZE = (P_WIDTH, P_HEIGHT)
F_WIDTH = 1280
F_HEIGHT = 768
F_SIZE = (F_WIDTH, F_HEIGHT)

SHOT_PIN = 16
PRINT_PIN = 15
NEXT_PIN = 13
PREV_PIN = 11

# Thread using the image full resolution
class CameraThread(threading.Thread):
    takeAshot = False
    exitNOshot = False
    stream2 = BytesIO()

    def __init__(self):
        threading.Thread.__init__(self)
        self.event = threading.Event()

    def run(self):
        global currentFileNumber
        for bug in camera.capture_continuous(self.stream2, format='jpeg', use_video_port=True, splitter_port=0):
            self.stream2.seek(0) # "Rewind" the stream to the beginning so we can read its content
            print('Capture thread: ', self.takeAshot)
            if self.takeAshot:
                image = Image.open(self.stream2)

                # Increment file number
                i = 1
                while os.path.exists("pz%05d.jpg" % i):
                    i += 1
                currentFileNumber = i
#
                # Save last to a jpeg file
                saveImageToFile(image, "pz%05d.jpg" % currentFileNumber)

                self.takeAshot = False
                break

            if self.exitNOshot:
                break

# Variables
currentFileNumber = -1

# GPIO setup
GPIO.setmode(GPIO.BOARD)
GPIO.setup(SHOT_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(PRINT_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(NEXT_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(PREV_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# add edge detection on a channel
GPIO.add_event_detect(SHOT_PIN, GPIO.FALLING, bouncetime=250)
GPIO.add_event_detect(PRINT_PIN, GPIO.FALLING, bouncetime=250)
GPIO.add_event_detect(NEXT_PIN, GPIO.FALLING, bouncetime=250)
GPIO.add_event_detect(PREV_PIN, GPIO.FALLING, bouncetime=250)

# Create Sharp mempry LCD
lcd = SMemLCD('/dev/spidev0.0')

# Create Printer
printer = Adafruit_Thermal("/dev/ttyAMA0", 115200, timeout=0, rtscts=True)

# Create camera and in-memory stream
stream = BytesIO()
camera = PiCamera()
camera.resolution = (F_WIDTH, F_HEIGHT)
camera.framerate = 8
camera.contrast = 50
camera.start_preview()
sleep(1)
#Printer resolution camera Thread to minimize shot delay
cameraThreadForPrint = CameraThread()

def displayImageFileOnLCD(filename):
    print 'displays ', filename
    title = 'Review Mode'
    # resize/dither to screen resolution and send to LCD
    image = Image.open(filename)
    im_width, im_height = image.size
    if im_width < im_height:
        image = image.rotate(90)
    image.thumbnail(S_SIZE, Image.ANTIALIAS)
    image_sized = Image.new('RGB', S_SIZE, (0, 0, 0))
    image_sized.paste(image,((S_SIZE[0] - image.size[0]) / 2, (S_SIZE[1] - image.size[1]) / 2))
    # draw filename
    draw = ImageDraw.Draw(image_sized)
    font = ImageFont.truetype('arial.ttf', 18)
    draw.rectangle([(0, 0), (115, 22)], fill=(255,255,255), outline=(0,0,0))
    draw.text((2, 2), title, fill='black', font=font)
    draw.rectangle([(279, 217), (399, 239)], fill=(255,255,255), outline=(0,0,0))
    draw.text((290, 218), filename, fill='black', font=font)
    # display on LCD
    image_sized = ImageOps.invert(image_sized)
    image_sized = image_sized.convert('1') # convert image to black and white
    lcd.write(image_sized.tobytes())

def printImageFile(filename):
    print 'prints ', filename
    # resize to printer resolution and send to printer
    image = Image.open(filename)
    im_width, im_height = image.size
    if im_width > im_height:
        image = image.rotate(90)
    image.thumbnail((P_HEIGHT, P_WIDTH), Image.ANTIALIAS)
    printer.printImage(image, False)
    printer.feed(3)

def saveImageToFile(image, filename):
    print 'saves image ', filename
    # save full image
    image.save(filename)

#Main loop
while True:
    # Restart shooting thread
    if not cameraThreadForPrint.isAlive():
        cameraThreadForPrint = CameraThread()
        cameraThreadForPrint.start()

    # View Loop
    stream.seek(0)
    for foo in camera.capture_continuous(stream, format='jpeg', use_video_port=True, resize=(S_WIDTH, S_HEIGHT), splitter_port=1):
        t1 = time.time()
        stream.seek(0) # "Rewind" the stream to the beginning so we can read its content
        image_source = Image.open(stream)
        imageInverted = ImageOps.invert(image_source)

        # convert image to black or white and send to LCD
        lcd.write(imageInverted.convert('1').tobytes())
        stream.seek(0)
        print('Live view : capture and display time: %f' % (time.time() - t1))

        if GPIO.event_detected(SHOT_PIN):
            cameraThreadForPrint.takeAshot = True
            break
        if GPIO.event_detected(PRINT_PIN):
            cameraThreadForPrint.exitNOshot = True
            break

    # Wait the picture is taken
    cameraThreadForPrint.join(5)

    # Set current file number if not set yet
    if currentFileNumber == -1 :
        i = 0
        while True:
            if os.path.exists("pz%05d.jpg" % (i+1)):
                i += 1
            else :
                break
        currentFileNumber = i

    # Display current image
    displayImageFileOnLCD("pz%05d.jpg" % currentFileNumber)

    # Review Loop
    while True:
        sleep(0.25)
        if GPIO.event_detected(NEXT_PIN):
            # Increment current file name and display it
            if os.path.exists("pz%05d.jpg" % (currentFileNumber+1)):
                currentFileNumber += 1
            displayImageFileOnLCD("pz%05d.jpg" % currentFileNumber)
        if GPIO.event_detected(PREV_PIN):
            # Decrement current file name and display it
            if os.path.exists("pz%05d.jpg" % (currentFileNumber-1)):
                currentFileNumber -= 1
            displayImageFileOnLCD("pz%05d.jpg" % currentFileNumber)
        if GPIO.event_detected(PRINT_PIN):
            # Print current file
            printImageFile("pz%05d.jpg" % currentFileNumber)
        if GPIO.event_detected(SHOT_PIN):
            # Exit review
            break

print("Main loop has exited")

<commit_msg>Add a shutdown button (sudo halt)<commit_after>'''
Created on 24 Jan 2017
@author: muth
'''
import os
import RPi.GPIO as GPIO
import threading
from Adafruit_Thermal import *
from time import sleep
from PIL import Image
from PIL import ImageOps
from PIL import ImageEnhance
from PIL import ImageDraw
from PIL import ImageFont
from smemlcd import SMemLCD
from picamera import PiCamera
from io import BytesIO

# Constants
S_WIDTH = 400
S_HEIGHT = 240
S_SIZE = (S_WIDTH, S_HEIGHT)
P_WIDTH = 640
P_HEIGHT = 384
P_SIZE = (P_WIDTH, P_HEIGHT)
F_WIDTH = 1280
F_HEIGHT = 768
F_SIZE = (F_WIDTH, F_HEIGHT)

SHOT_PIN = 16
PRINT_PIN = 15
NEXT_PIN = 13
PREV_PIN = 11
HALT_PIN = 31

# Thread using the image full resolution
class CameraThread(threading.Thread):
    takeAshot = False
    exitNOshot = False
    stream2 = BytesIO()

    def __init__(self):
        threading.Thread.__init__(self)
        self.event = threading.Event()

    def run(self):
        global currentFileNumber
        for bug in camera.capture_continuous(self.stream2, format='jpeg', use_video_port=True, splitter_port=0):
            self.stream2.seek(0) # "Rewind" the stream to the beginning so we can read its content
#             print('Capture thread: ', self.takeAshot)
            if self.takeAshot:
                image = Image.open(self.stream2)

                # Increment file number
                i = 1
                while os.path.exists("pz%05d.jpg" % i):
                    i += 1
                currentFileNumber = i
#
                # Save last to a jpeg file
                saveImageToFile(image, "pz%05d.jpg" % currentFileNumber)

                self.takeAshot = False
                break

            if self.exitNOshot:
                break

# Variables
currentFileNumber = -1

# GPIO setup
GPIO.setmode(GPIO.BOARD)
GPIO.setup(SHOT_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(PRINT_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(NEXT_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(PREV_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(HALT_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# add edge detection on a channel
GPIO.add_event_detect(SHOT_PIN, GPIO.FALLING, bouncetime=250)
GPIO.add_event_detect(PRINT_PIN, GPIO.FALLING, bouncetime=250)
GPIO.add_event_detect(NEXT_PIN, GPIO.FALLING, bouncetime=250)
GPIO.add_event_detect(PREV_PIN, GPIO.FALLING, bouncetime=250)

# Create Sharp mempry LCD
lcd = SMemLCD('/dev/spidev0.0')

# Create Printer
printer = Adafruit_Thermal("/dev/ttyAMA0", 115200, timeout=0, rtscts=True)

# Create camera and in-memory stream
stream = BytesIO()
camera = PiCamera()
camera.rotation = 180
camera.resolution = (F_WIDTH, F_HEIGHT)
camera.framerate = 8
camera.contrast = 50
camera.start_preview()
sleep(1)
#Printer resolution camera Thread to minimize shot delay
cameraThreadForPrint = CameraThread()

def haltSystem(channel):
    print 'Halt...'
    os.system("sudo halt")

GPIO.add_event_detect(31, GPIO.FALLING, callback = haltSystem, bouncetime = 2000)

def displayImageFileOnLCD(filename):
    print 'displays ', filename
    title = 'Review Mode'
    # resize/dither to screen resolution and send to LCD
    image = Image.open(filename)
    im_width, im_height = image.size
    if im_width < im_height:
        image = image.rotate(90)
    image.thumbnail(S_SIZE, Image.ANTIALIAS)
    image_sized = Image.new('RGB', S_SIZE, (0, 0, 0))
    image_sized.paste(image,((S_SIZE[0] - image.size[0]) / 2, (S_SIZE[1] - image.size[1]) / 2))
    # draw filename
    draw = ImageDraw.Draw(image_sized)
    font = ImageFont.truetype('arial.ttf', 18)
    draw.rectangle([(0, 0), (115, 22)], fill=(255,255,255), outline=(0,0,0))
    draw.text((2, 2), title, fill='black', font=font)
    draw.rectangle([(279, 217), (399, 239)], fill=(255,255,255), outline=(0,0,0))
    draw.text((290, 218), filename, fill='black', font=font)
    # display on LCD
    image_sized = ImageOps.invert(image_sized)
    image_sized = image_sized.convert('1') # convert image to black and white
    lcd.write(image_sized.tobytes())

def printImageFile(filename):
    print 'prints ', filename
    # resize to printer resolution and send to printer
    image = Image.open(filename)
    im_width, im_height = image.size
    if im_width > im_height:
        image = image.rotate(90)
    image.thumbnail((P_HEIGHT, P_WIDTH), Image.ANTIALIAS)
    printer.printImage(image, False)
    printer.feed(3)

def saveImageToFile(image, filename):
    print 'saves image ', filename
    # save full image
    image.save(filename)

#Main loop
while True:
    # Restart shooting thread
    if not cameraThreadForPrint.isAlive():
        cameraThreadForPrint = CameraThread()
        cameraThreadForPrint.start()

    # View Loop
    stream.seek(0)
    for foo in camera.capture_continuous(stream, format='jpeg', use_video_port=True, resize=(S_WIDTH, S_HEIGHT), splitter_port=1):
        t1 = time.time()
        stream.seek(0) # "Rewind" the stream to the beginning so we can read its content
        image_source = Image.open(stream)
        imageInverted = ImageOps.invert(image_source)

        # convert image to black or white and send to LCD
        lcd.write(imageInverted.convert('1').tobytes())
        stream.seek(0)
#         print('Live view : capture and display time: %f' % (time.time() - t1))

        if GPIO.event_detected(SHOT_PIN):
            cameraThreadForPrint.takeAshot = True
            break
        if GPIO.event_detected(PRINT_PIN):
            cameraThreadForPrint.exitNOshot = True
            break

    # Wait the picture is taken
    cameraThreadForPrint.join(5)

    # Set current file number if not set yet
    if currentFileNumber == -1 :
        i = 0
        while True:
            if os.path.exists("pz%05d.jpg" % (i+1)):
                i += 1
            else :
                break
        currentFileNumber = i

    # Display current image
    displayImageFileOnLCD("pz%05d.jpg" % currentFileNumber)

    # Review Loop
    while True:
        sleep(0.25)
        if GPIO.event_detected(NEXT_PIN):
            # Increment current file name and display it
            if os.path.exists("pz%05d.jpg" % (currentFileNumber+1)):
                currentFileNumber += 1
            displayImageFileOnLCD("pz%05d.jpg" % currentFileNumber)
        if GPIO.event_detected(PREV_PIN):
            # Decrement current file name and display it
            if os.path.exists("pz%05d.jpg" % (currentFileNumber-1)):
                currentFileNumber -= 1
            displayImageFileOnLCD("pz%05d.jpg" % currentFileNumber)
        if GPIO.event_detected(PRINT_PIN):
            # Print current file
            printImageFile("pz%05d.jpg" % currentFileNumber)
        if GPIO.event_detected(SHOT_PIN):
            # Exit review
            break

print("Main loop has exited")

<|endoftext|>


<commit_before>#!/usr/bin/env python
"""
This thing assumes you're throwing it at a CSV that ends in .csv or .CSV or similar.
Your full address field -- "1600 Pennsylvania Ave. NW, Washington, D.C., USA" -- MUST be the final column.
"""

from __future__ import print_function
import argparse
import sys
import csv
import os
import time

from geopy.geocoders import GoogleV3
from geopy.exc import GeocoderTimedOut

import creds

try:
    GoogleAPIkey = creds.setup['GoogleAPIkey']
except KeyError:
    print("You need to configure your Google geocoding API key in creds.py. Instructions are there.")
    print("It's not as scary as it sounds, if you've never done this before.")
    sys.exit()
if GoogleAPIkey == "GetYourKeyUsingTheDirectionsAbove":
    print("You need to configure your Google geocoding API key in creds.py. Instructions are there.")
    print("It's not as scary as it sounds, if you've never done this before.")
    sys.exit()

try:
    geocachepath = creds.setup['geocachepath']
except KeyError:
    print("You need to figure a setup['geocachepath'] within creds.py to meet the new file format.")
    print("Check the sample on Github.com/PalmBeachPost/postgeo to figure out how to update your version.")
    sys.exit()

geolocator = GoogleV3(api_key=GoogleAPIkey, timeout=10)

def timedisplay(timediff):
    m, s = divmod(timediff, 60)
    h, m = divmod(m, 60)
    return("%d:%02d:%02d" % (h, m, s))

def main(geocacheflag):
    # Start building caching as we go along.
    # Format: Full address as key, value as a tuple of lat, long, accuracy, lat-long
    geocache = {"1600 Pennsylvania Ave. NW, Washington, D.C. 20500":
                ("-77.036482", "38.897667", "Rooftop", "-77.036482, 38.897667")}
    inputfilename = args.filename
    buffersize = 1
    totalrows = 0
    rowsprocessed = 0
    lastpercentageprocessed = 0
    starttime = time.clock()

    outputfilename = inputfilename[:inputfilename.rfind(".")] + "-geo" + inputfilename[inputfilename.rfind("."):]

    if os.path.isfile(outputfilename):
        message = "File {} exists, proceeding will overwrite(y or n)? "
        proceed_prompt = get_input(message.format(outputfilename))
        if proceed_prompt.lower() == 'y':
            pass
        else:
            print('Aborting . . .')
            exit()

# Read from geocache.csv file, if selected as option at command line.
    if geocacheflag == 1:
        if not os.path.isfile(geocachepath):
            print("Using " + geocachepath + " file to speed up results.")
            with open(geocachepath, 'wb') as cachefilehandle:
                        # with open(geocachepath, 'wb', buffersize) as cachefilehandle:
                cacheput = csv.writer(cachefilehandle)
                geocacheheader = ['fulladdy', 'lat', 'long', 'accuracy', 'latlong']
                cacheput.writerow(geocacheheader)
                for fulladdy in geocache:
                    mylat, mylong, myaccuracy, mylatlong = geocache[fulladdy]
                    myrow = [fulladdy, mylat, mylong, myaccuracy, mylatlong]
                    cacheput.writerow(myrow)

        else:       # If we have that geocachepath file
            print("Using " + geocachepath + " file to speed up results.")
            with open(geocachepath, 'rU') as cachefilehandle:
                rows = csv.reader(cachefilehandle)
                rows.next()        # Skip header row
                for row in rows:
                    if len(row) > 4:        # If we have a blank row, skip it.
                        if row[0] not in geocache:          # check for repeats of fulladdy as key
                            geocache[row[0]] = (row[1], row[2], row[3], row[4])
                        # Geocache should be fully set up now.
# Cache file should now be closed. Let's open it again to append to it.
        cachefilehandle = open(geocachepath, "ab")       # Open to append
        cacheput = csv.writer(cachefilehandle)
#
# Note we still have the file handle open for our cache. This is a good thing, but we do need to remember to write and close.
#

# Next, we open the source data CSV entirely to get a row count, then close it.
    with open(inputfilename, 'rU') as inputfilehandle:
            rows = csv.reader(inputfilehandle)
            for row in rows:
                totalrows += 1
            print(str(totalrows) + " rows to be processed.")

    with open(outputfilename, 'wb', buffersize) as outputfile:
        put = csv.writer(outputfile)
        with open(inputfilename, 'rU') as inputfilehandle:
            rows = csv.reader(inputfilehandle)
            headers = next(rows)
            headers.append("lat")
            headers.append("long")
            headers.append("accuracy")
            headers.append("latlong")
            put.writerow(headers)
            # print headers
            for row in rows:
                # print(row)
                fulladdy = row[-1]      # Last column of the file
                if fulladdy in geocache:
                    print("\tFound in cache: " + fulladdy)
                    mylat, mylong, myaccuracy, mylatlong = geocache[fulladdy]
                    row.append(mylat)
                    row.append(mylong)
                    row.append(myaccuracy)
                    row.append(mylatlong)
                    put.writerow(row)
                    rowsprocessed += 1

                    outputfile.flush()  # Force writes after each line. Should be no performance hit because geocoding is so slow.

                else:
                    if len(fulladdy) > 0:
                        location = geolocator.geocode(fulladdy.replace("'", ""))
                        try:
                            mylatlong = str(location.latitude) + ", " + str(location.longitude)
                            mylat = str(location.latitude)
                            mylong = str(location.longitude)
                            myaccuracy = location.raw["geometry"]["location_type"]
                            row.append(mylat)
                            row.append(mylong)
                            row.append(myaccuracy)
                            row.append(mylatlong)
                            geocache[fulladdy] = (mylat, mylong, myaccuracy, mylatlong)
                            rowsprocessed += 1
                            percentageprocessed = int(100*rowsprocessed/totalrows)
                            if percentageprocessed > lastpercentageprocessed:
                                lastpercentageprocessed = percentageprocessed
                                endtime = time.clock()
                                timediff = (endtime-starttime)
                                print(str(percentageprocessed) + "% processed in " + timedisplay(timediff) + ". ETA: " + timedisplay((timediff/rowsprocessed)*(totalrows-rowsprocessed)) + ".")

                            put.writerow(row)
                            outputfile.flush()
                            print("Found: " + fulladdy)
                            lastfulladdy = fulladdy
                            lastlat = mylat
                            lastlong = mylong
                            lastaccuracy = myaccuracy
                            lastlatlong = mylatlong
                            if geocacheflag == 1:
                                cacheput.writerow([fulladdy, mylat, mylong, myaccuracy, mylatlong])
                                cachefilehandle.flush()

                            time.sleep(1)       # Necessary to avoid getting shut out

                        except AttributeError:
                            if len(fulladdy) > 0:
                                print("Dropping row: Something went wrong on " + fulladdy)
                                rowsprocessed += 1
                            else:
                                print("Dropping row: No address listed in this row: " + str(row))
                                rowsprocessed += 1
                        except GeocoderTimedOut:
                            print("Geocoder service timed out on this row: " + str(row))
                            rowsprocessed += 1
                    else:           # If fulladdy was blank
                            print("Dropping row: No address listed in this row: " + str(row))
                            rowsprocessed += 1

    if geocacheflag == 1:
        cachefilehandle.flush()
        cachefilehandle.close()

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="postgeo.py is a command-line geocoder tool.")
    parser.add_argument('filename', metavar='filename', help='CSV file containing addresses to be geocoded')
    parser.add_argument('-c', help='Use geocache.csv file to speed up coding and recoding. Now the default.', action="store_true")
    parser.add_argument('-n', help='Do NOT use geocache file Use geocache.csv file to speed up geocoding and recoding.', action="store_true")
    try:
        args = parser.parse_args()
    except:
        parser.print_help()
        sys.exit(1)
    get_input = input

    if sys.version_info[:2] <= (2, 7):
        get_input = raw_input

    if args.n:
        geocacheflag = 0
    else:
        geocacheflag = 1

    if args.c:      # If we get both options
        geocacheflag = 1
    if geocacheflag == 1:
        print("Speeding up results with cached file " + geocachepath)

    if args.filename.lower().endswith('.csv'):
        if os.path.isfile(args.filename):
            print("Beginning to process " + args.filename)
            main(geocacheflag)
        else:
            print("File " + args.filename + " not found.")

    else:
        print("File must be of type CSV and end with .csv extension")
<commit_msg>More delays to not overwhelm the geocoder<commit_after>#!/usr/bin/env python
"""
This thing assumes you're throwing it at a CSV that ends in .csv or .CSV or similar.
Your full address field -- "1600 Pennsylvania Ave. NW, Washington, D.C., USA" -- MUST be the final column.
"""

from __future__ import print_function
import argparse
import sys
import csv
import os
import time

from geopy.geocoders import GoogleV3
from geopy.exc import GeocoderTimedOut

import creds

try:
    GoogleAPIkey = creds.setup['GoogleAPIkey']
except KeyError:
    print("You need to configure your Google geocoding API key in creds.py. Instructions are there.")
    print("It's not as scary as it sounds, if you've never done this before.")
    sys.exit()
if GoogleAPIkey == "GetYourKeyUsingTheDirectionsAbove":
    print("You need to configure your Google geocoding API key in creds.py. Instructions are there.")
    print("It's not as scary as it sounds, if you've never done this before.")
    sys.exit()

try:
    geocachepath = creds.setup['geocachepath']
except KeyError:
    print("You need to figure a setup['geocachepath'] within creds.py to meet the new file format.")
    print("Check the sample on Github.com/PalmBeachPost/postgeo to figure out how to update your version.")
    sys.exit()

geolocator = GoogleV3(api_key=GoogleAPIkey, timeout=10)

def timedisplay(timediff):
    m, s = divmod(timediff, 60)
    h, m = divmod(m, 60)
    return("%d:%02d:%02d" % (h, m, s))

def main(geocacheflag):
    # Start building caching as we go along.
    # Format: Full address as key, value as a tuple of lat, long, accuracy, lat-long
    geocache = {"1600 Pennsylvania Ave. NW, Washington, D.C. 20500":
                ("-77.036482", "38.897667", "Rooftop", "-77.036482, 38.897667")}
    inputfilename = args.filename
    buffersize = 1
    totalrows = 0
    rowsprocessed = 0
    lastpercentageprocessed = 0
    starttime = time.clock()

    outputfilename = inputfilename[:inputfilename.rfind(".")] + "-geo" + inputfilename[inputfilename.rfind("."):]

    if os.path.isfile(outputfilename):
        message = "File {} exists, proceeding will overwrite(y or n)? "
        proceed_prompt = get_input(message.format(outputfilename))
        if proceed_prompt.lower() == 'y':
            pass
        else:
            print('Aborting . . .')
            exit()

# Read from geocache.csv file, if selected as option at command line.
    if geocacheflag == 1:
        if not os.path.isfile(geocachepath):
            print("Using " + geocachepath + " file to speed up results.")
            with open(geocachepath, 'wb') as cachefilehandle:
                        # with open(geocachepath, 'wb', buffersize) as cachefilehandle:
                cacheput = csv.writer(cachefilehandle)
                geocacheheader = ['fulladdy', 'lat', 'long', 'accuracy', 'latlong']
                cacheput.writerow(geocacheheader)
                for fulladdy in geocache:
                    mylat, mylong, myaccuracy, mylatlong = geocache[fulladdy]
                    myrow = [fulladdy, mylat, mylong, myaccuracy, mylatlong]
                    cacheput.writerow(myrow)

        else:       # If we have that geocachepath file
            print("Using " + geocachepath + " file to speed up results.")
            with open(geocachepath, 'rU') as cachefilehandle:
                rows = csv.reader(cachefilehandle)
                rows.next()        # Skip header row
                for row in rows:
                    if len(row) > 4:        # If we have a blank row, skip it.
                        if row[0] not in geocache:          # check for repeats of fulladdy as key
                            geocache[row[0]] = (row[1], row[2], row[3], row[4])
                        # Geocache should be fully set up now.
# Cache file should now be closed. Let's open it again to append to it.
        cachefilehandle = open(geocachepath, "ab")       # Open to append
        cacheput = csv.writer(cachefilehandle)
#
# Note we still have the file handle open for our cache. This is a good thing, but we do need to remember to write and close.
#

# Next, we open the source data CSV entirely to get a row count, then close it.
    with open(inputfilename, 'rU') as inputfilehandle:
            rows = csv.reader(inputfilehandle)
            for row in rows:
                totalrows += 1
            print(str(totalrows) + " rows to be processed.")

    with open(outputfilename, 'wb', buffersize) as outputfile:
        put = csv.writer(outputfile)
        with open(inputfilename, 'rU') as inputfilehandle:
            rows = csv.reader(inputfilehandle)
            headers = next(rows)
            headers.append("lat")
            headers.append("long")
            headers.append("accuracy")
            headers.append("latlong")
            put.writerow(headers)
            # print headers
            for row in rows:
                # print(row)
                fulladdy = row[-1]      # Last column of the file
                if fulladdy in geocache:
                    print("\tFound in cache: " + fulladdy)
                    mylat, mylong, myaccuracy, mylatlong = geocache[fulladdy]
                    row.append(mylat)
                    row.append(mylong)
                    row.append(myaccuracy)
                    row.append(mylatlong)
                    put.writerow(row)
                    rowsprocessed += 1

                    outputfile.flush()  # Force writes after each line. Should be no performance hit because geocoding is so slow.

                else:
                    if len(fulladdy) > 0:
                        location = geolocator.geocode(fulladdy.replace("'", ""))
                        try:
                            mylatlong = str(location.latitude) + ", " + str(location.longitude)
                            mylat = str(location.latitude)
                            mylong = str(location.longitude)
                            myaccuracy = location.raw["geometry"]["location_type"]
                            row.append(mylat)
                            row.append(mylong)
                            row.append(myaccuracy)
                            row.append(mylatlong)
                            geocache[fulladdy] = (mylat, mylong, myaccuracy, mylatlong)
                            rowsprocessed += 1
                            percentageprocessed = int(100*rowsprocessed/totalrows)
                            if percentageprocessed > lastpercentageprocessed:
                                lastpercentageprocessed = percentageprocessed
                                endtime = time.clock()
                                timediff = (endtime-starttime)
                                print(str(percentageprocessed) + "% processed in " + timedisplay(timediff) + ". ETA: " + timedisplay((timediff/rowsprocessed)*(totalrows-rowsprocessed)) + ".")

                            put.writerow(row)
                            outputfile.flush()
                            print("Found: " + fulladdy)
                            lastfulladdy = fulladdy
                            lastlat = mylat
                            lastlong = mylong
                            lastaccuracy = myaccuracy
                            lastlatlong = mylatlong
                            if geocacheflag == 1:
                                cacheput.writerow([fulladdy, mylat, mylong, myaccuracy, mylatlong])
                                cachefilehandle.flush()

                            time.sleep(1)       # Necessary to avoid getting shut out

                        except AttributeError:
                            if len(fulladdy) > 0:
                                print("Dropping row: Something went wrong on " + fulladdy)
                                time.sleep(1)
                                rowsprocessed += 1
                            else:
                                print("Dropping row: No address listed in this row: " + str(row))
                                rowsprocessed += 1
                        except GeocoderTimedOut:
                            print("Geocoder service timed out on this row: " + str(row))
                            print("You should probably re-run this on the next pass.")
                            time.sleep(1)
                            rowsprocessed += 1
                    else:           # If fulladdy was blank
                            print("Dropping row: No address listed in this row: " + str(row))
                            rowsprocessed += 1

    if geocacheflag == 1:
        cachefilehandle.flush()
        cachefilehandle.close()

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="postgeo.py is a command-line geocoder tool.")
    parser.add_argument('filename', metavar='filename', help='CSV file containing addresses to be geocoded')
    parser.add_argument('-c', help='Use geocache.csv file to speed up coding and recoding. Now the default.', action="store_true")
    parser.add_argument('-n', help='Do NOT use geocache file Use geocache.csv file to speed up geocoding and recoding.', action="store_true")
    try:
        args = parser.parse_args()
    except:
        parser.print_help()
        sys.exit(1)
    get_input = input

    if sys.version_info[:2] <= (2, 7):
        get_input = raw_input

    if args.n:
        geocacheflag = 0
    else:
        geocacheflag = 1

    if args.c:      # If we get both options
        geocacheflag = 1
    if geocacheflag == 1:
        print("Speeding up results with cached file " + geocachepath)

    if args.filename.lower().endswith('.csv'):
        if os.path.isfile(args.filename):
            print("Beginning to process " + args.filename)
            main(geocacheflag)
        else:
            print("File " + args.filename + " not found.")

    else:
        print("File must be of type CSV and end with .csv extension")
<|endoftext|>


<commit_before>#!/usr/bin/env python
"""
This thing assumes you're throwing it at a CSV that ends in .csv or .CSV or similar.
Your full address field -- "1600 Pennsylvania Ave. NW, Washington, D.C., USA" -- MUST be the final column.
"""

from __future__ import print_function
import argparse
import sys
import csv
import os
import time

from geopy.geocoders import GoogleV3
from geopy.exc import GeocoderTimedOut

import creds

GoogleAPIkey = creds.access['GoogleAPIkey']

geolocator = GoogleV3(api_key=GoogleAPIkey, timeout=10)

# Let's set up a buffer, in case we're running with a sorted list that has overlapping points.

def main():
    lastfulladdy = "1600 Pennsylvania Ave. NW, Washington, D.C. 20500"
    lastlat = "-77.036482"
    lastlong = "38.897667"
    lastaccuracy = "Rooftop"
    lastlatlong = "-77.036482, 38.897667"
    inputfilename = args.filename
    buffersize = 1

    outputfilename = inputfilename[:inputfilename.rfind(".")] + "-geo" + inputfilename[inputfilename.rfind("."):]

    if os.path.isfile(outputfilename):
        message = "File {} exists, proceeding will overwrite(y or n)? "
        proceed_prompt = get_input(message.format(outputfilename))
        if proceed_prompt.lower() == 'y':
            pass
        else:
            print('Aborting . . .')
            exit()

    with open(outputfilename, 'wb', buffersize) as outputfile:
#        put = csv.writer(outputfile, lineterminator='\n')
        put = csv.writer(outputfile)
        with open(inputfilename, 'rU') as inputfilehandle:
            rows = csv.reader(inputfilehandle)
            headers = next(rows)
            headers.append("lat")
            headers.append("long")
            headers.append("accuracy")
            headers.append("latlong")
            put.writerow(headers)
#            print headers
            for row in rows:
#                print(row)
                fulladdy = row[-1]
                if fulladdy == lastfulladdy:
                    print("Repeated address found for " + fulladdy)
                    row.append(lastlat)
                    row.append(lastlong)
                    row.append(lastaccuracy)
                    row.append(lastlatlong)
                    put.writerow(row)
                    outputfile.flush()
                    os.fsync()
                else:
                    location = geolocator.geocode(fulladdy)
                    try:
                        mylatlong = str(location.latitude) + ", " + str(location.longitude)
                        mylat = str(location.latitude)
                        mylong = str(location.longitude)
                        myaccuracy = location.raw["geometry"]["location_type"]
                        row.append(mylat)
                        row.append(mylong)
                        row.append(myaccuracy)
                        row.append(mylatlong)
                        put.writerow(row)
                        print("Found: " + fulladdy)
                        lastfulladdy = fulladdy
                        lastlat = mylat
                        lastlong = mylong
                        lastaccuracy = myaccuracy
                        lastlatlong = mylatlong
                        time.sleep(1)       # Necessary to avoid getting shut out
                    except AttributeError:
                        if len(fulladdy)>0:
                            print("Dropping row: Something went wrong on " + fulladdy)
                        else:
                            print("Dropping row: No address listed in this row: " + str(row))
                    except GeocoderTimedOut:
                        print("Geocoder service timed out on this row: " + str(row))

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Address file to geocode")
    parser.add_argument('filename', metavar='filename', help='CSV file containing addresses to be geocoded')
    try:
        args = parser.parse_args()
    except:
        parser.print_help()
        sys.exit(1)
    get_input = input

    if sys.version_info[:2] <= (2, 7):
        get_input = raw_input

    if args.filename.lower().endswith('.csv'):
        print(args.filename)
        main()
    else:
        print("File must be of type CSV and end with .csv extension")
<commit_msg>Patched error handling. Forcing regular commits.<commit_after>#!/usr/bin/env python
"""
This thing assumes you're throwing it at a CSV that ends in .csv or .CSV or similar.
Your full address field -- "1600 Pennsylvania Ave. NW, Washington, D.C., USA" -- MUST be the final column.
"""

from __future__ import print_function
import argparse
import sys
import csv
import os
import time

from geopy.geocoders import GoogleV3
from geopy.exc import GeocoderTimedOut

import creds

GoogleAPIkey = creds.access['GoogleAPIkey']

geolocator = GoogleV3(api_key=GoogleAPIkey, timeout=10)

# Let's set up a buffer, in case we're running with a sorted list that has overlapping points.

def main():
    lastfulladdy = "1600 Pennsylvania Ave. NW, Washington, D.C. 20500"
    lastlat = "-77.036482"
    lastlong = "38.897667"
    lastaccuracy = "Rooftop"
    lastlatlong = "-77.036482, 38.897667"
    inputfilename = args.filename
    buffersize = 1

    outputfilename = inputfilename[:inputfilename.rfind(".")] + "-geo" + inputfilename[inputfilename.rfind("."):]

    if os.path.isfile(outputfilename):
        message = "File {} exists, proceeding will overwrite(y or n)? "
        proceed_prompt = get_input(message.format(outputfilename))
        if proceed_prompt.lower() == 'y':
            pass
        else:
            print('Aborting . . .')
            exit()

    with open(outputfilename, 'wb', buffersize) as outputfile:
#        put = csv.writer(outputfile, lineterminator='\n')
        put = csv.writer(outputfile)
        with open(inputfilename, 'rU') as inputfilehandle:
            rows = csv.reader(inputfilehandle)
            headers = next(rows)
            headers.append("lat")
            headers.append("long")
            headers.append("accuracy")
            headers.append("latlong")
            put.writerow(headers)
#            print headers
            for row in rows:
#                print(row)
                fulladdy = row[-1]
                if fulladdy == lastfulladdy:
                    print("Repeated address found for " + fulladdy)
                    row.append(lastlat)
                    row.append(lastlong)
                    row.append(lastaccuracy)
                    row.append(lastlatlong)
                    put.writerow(row)
                    outputfile.flush()
                    os.fsync()          # Force writes after each line. Should be no performance hit because geocoding
                                        # is so slow.
                else:
                    location = geolocator.geocode(fulladdy)
                    try:
                        mylatlong = str(location.latitude) + ", " + str(location.longitude)
                        mylat = str(location.latitude)
                        mylong = str(location.longitude)
                        myaccuracy = location.raw["geometry"]["location_type"]
                        row.append(mylat)
                        row.append(mylong)
                        row.append(myaccuracy)
                        row.append(mylatlong)
                        put.writerow(row)
                        print("Found: " + fulladdy)
                        lastfulladdy = fulladdy
                        lastlat = mylat
                        lastlong = mylong
                        lastaccuracy = myaccuracy
                        lastlatlong = mylatlong
                        time.sleep(1)       # Necessary to avoid getting shut out
                    except AttributeError:
                        if len(fulladdy)>0:
                            print("Dropping row: Something went wrong on " + fulladdy)
                        else:
                            print("Dropping row: No address listed in this row: " + str(row))
                    except GeocoderTimedOut:
                        print("Geocoder service timed out on this row: " + str(row))

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Address file to geocode")
    parser.add_argument('filename', metavar='filename', help='CSV file containing addresses to be geocoded')
    try:
        args = parser.parse_args()
    except:
        parser.print_help()
        sys.exit(1)
    get_input = input

    if sys.version_info[:2] <= (2, 7):
        get_input = raw_input

    if args.filename.lower().endswith('.csv'):
        print(args.filename)
        main()
    else:
        print("File must be of type CSV and end with .csv extension")
<|endoftext|>