· 7 years ago · Oct 27, 2018, 02:12 PM
1import platform
2import os
3import uuid
4import urllib2
5import json
6import traceback
7import tempfile
8import re
9import getpass
10#import configparser
11import sys
12import argparse
13import random
14import telly
15import robot_util
16
17parser = argparse.ArgumentParser(description='start robot control program')
18parser.add_argument('robot_id', help='Robot ID')
19parser.add_argument('--info-server', help="Server that robot will connect to for information about servers and things", default='letsrobot.tv')
20parser.add_argument('--type', help="Serial or motor_hat or gopigo2 or gopigo3 or l298n or motozero or pololu or mdd10", default='motor_hat')
21parser.add_argument('--serial-device', help="Serial device", default='/dev/ttyACM0')
22parser.add_argument('--male', dest='male', action='store_true')
23parser.add_argument('--female', dest='male', action='store_false')
24parser.add_argument('--voice-number', type=int, default=1)
25parser.add_argument('--led', help="Type of LED for example max7219", default=None)
26parser.add_argument('--ledrotate', help="Rotates the LED matrix. Example: 180", default=None)
27parser.add_argument('--tts-volume', type=int, default=80)
28parser.add_argument('--secret-key', default=None)
29parser.add_argument('--turn-delay', type=float, default=0.4)
30parser.add_argument('--straight-delay', type=float, default=0.5)
31parser.add_argument('--driving-speed', type=int, default=90)
32parser.add_argument('--day-speed', type=int, default=255)
33parser.add_argument('--night-speed', type=int, default=255)
34parser.add_argument('--forward', default='[-1,1,-1,1]')
35parser.add_argument('--left', default='[1,1,1,1]')
36parser.add_argument('--festival-tts', dest='festival_tts', action='store_true')
37parser.set_defaults(festival_tts=False)
38parser.add_argument('--auto-wifi', dest='auto_wifi', action='store_true')
39parser.set_defaults(auto_wifi=False)
40parser.add_argument('--no-anon-tts', dest='anon_tts', action='store_false')
41parser.set_defaults(anon_tts=True)
42parser.add_argument('--no-chat-server-connection', dest='enable_chat_server_connection', action='store_false')
43parser.set_defaults(enable_chat_server_connection=True)
44parser.add_argument('--no-secure-cert', dest='secure_cert', action='store_false')
45parser.set_defaults(secure_cert=True)
46parser.add_argument('--filter-url-tts', dest='filter_url_tts', action='store_true')
47parser.set_defaults(filter_url_tts=False)
48parser.add_argument('--slow-for-low-battery', dest='slow_for_low_battery', action='store_true')
49parser.set_defaults(slow_for_low_battery=False)
50parser.add_argument('--reverse-ssh-key-file', default='/home/pi/reverse_ssh_key1.pem')
51parser.add_argument('--reverse-ssh-host', default='ubuntu@52.52.204.174')
52parser.add_argument('--charge-hours', type=float, default = 3.0)
53parser.add_argument('--discharge-hours', type=float, default = 8.0)
54parser.add_argument('--right-wheel-forward-speed', type=int)
55parser.add_argument('--right-wheel-backward-speed', type=int)
56parser.add_argument('--left-wheel-forward-speed', type=int)
57parser.add_argument('--left-wheel-backward-speed', type=int)
58parser.add_argument('--led-max-brightness', type=int)
59parser.add_argument('--speaker-device', default=2, type=int)
60parser.add_argument('--tts-delay-enabled', dest='tts_delay_enabled', action='store_true')
61parser.add_argument('--tts-delay-seconds', dest='tts_delay_seconds', type=int, default=5)
62parser.add_argument('--woot-room', help="Room to enable woot events", default='')
63
64commandArgs = parser.parse_args()
65print commandArgs
66
67chargeCheckInterval = 5
68chargeValue = 0.0
69secondsToCharge = 60.0 * 60.0 * commandArgs.charge_hours
70secondsToDischarge = 60.0 * 60.0 * commandArgs.discharge_hours
71
72maxSpeedEnabled = False
73
74# watch dog timer
75os.system("sudo modprobe bcm2835_wdt")
76os.system("sudo /usr/sbin/service watchdog start")
77
78
79# set volume level
80
81# tested for 3.5mm audio jack
82os.system("amixer set PCM -- 100%d%%" % commandArgs.tts_volume)
83#if commandArgs.tts_volume > 50:
84 #os.system("amixer set PCM -- -100")
85
86# tested for USB audio device
87os.system("amixer -c %d cset numid=3 %d%%" % (commandArgs.speaker_device, commandArgs.tts_volume))
88
89
90infoServer = commandArgs.info_server
91#infoServer = "letsrobot.tv"
92#infoServer = "runmyrobot.com"
93#infoServer = "52.52.213.92"
94#infoServer = "letsrobot.tv:3100"
95
96print "info server:", infoServer
97
98tempDir = tempfile.gettempdir()
99print "temporary directory:", tempDir
100
101
102# motor controller specific intializations
103if commandArgs.type == 'none':
104 pass
105elif commandArgs.type == 'serial':
106 import serial
107elif commandArgs.type == 'motor_hat':
108 pass
109elif commandArgs.type == 'mebo2':
110 from mebo.handle_mebo_command import handle_mebo_command
111elif commandArgs.type == 'gopigo2':
112 import gopigo
113elif commandArgs.type == 'gopigo3':
114 sys.path.append("/home/pi/Dexter/GoPiGo3/Software/Python")
115 import easygopigo3
116 easyGoPiGo3 = easygopigo3.EasyGoPiGo3()
117elif commandArgs.type == 'l298n':
118 try:
119 import configparser
120 except ImportError:
121 print "You need to install configparser (sudo python -m pip install configparser)\n Ctrl-C to quit"
122 while True:
123 pass # Halt program to avoid error down the line.
124elif commandArgs.type == 'motozero':
125 pass
126elif commandArgs.type == 'pololu':
127 pass
128elif commandArgs.type == 'screencap':
129 pass
130elif commandArgs.type == 'adafruit_pwm':
131 from Adafruit_PWM_Servo_Driver import PWM
132elif commandArgs.led == 'max7219':
133 import spidev
134elif commandArgs.type == 'owi_arm':
135 import owi_arm
136elif commandArgs.type == 'mdd10':
137 pass
138else:
139 print "invalid --type in command line"
140 exit(0)
141
142serialDevice = commandArgs.serial_device
143
144if commandArgs.type == 'motor_hat':
145 try:
146 from Adafruit_MotorHAT import Adafruit_MotorHAT, Adafruit_DCMotor
147 motorsEnabled = True
148 except ImportError:
149 print "You need to install Adafruit_MotorHAT"
150 print "Please install Adafruit_MotorHAT for python and restart this script."
151 print "To install: cd /usr/local/src && sudo git clone https://github.com/adafruit/Adafruit-Motor-HAT-Python-Library.git"
152 print "cd /usr/local/src/Adafruit-Motor-HAT-Python-Library && sudo python setup.py install"
153 print "Running in test mode."
154 print "Ctrl-C to quit"
155 motorsEnabled = False
156
157# todo: specificity is not correct, this is specific to a bot with a claw, not all motor_hat based bots
158if commandArgs.type == 'motor_hat':
159 from Adafruit_PWM_Servo_Driver import PWM
160
161import time
162import atexit
163import sys
164import thread
165import subprocess
166if (commandArgs.type == 'motor_hat') or (commandArgs.type == 'l298n') or (commandArgs.type == 'motozero'):
167 import RPi.GPIO as GPIO
168import datetime
169from socketIO_client import SocketIO, LoggingNamespace
170
171chargeIONumber = 17
172robotID = commandArgs.robot_id
173
174if commandArgs.type == 'motor_hat':
175 GPIO.setmode(GPIO.BCM)
176 GPIO.setup(chargeIONumber, GPIO.IN)
177if commandArgs.type == 'l298n':
178 mode=GPIO.getmode()
179 print " mode ="+str(mode)
180 GPIO.cleanup()
181 #Change the GPIO Pins to your connected motors in gpio.conf
182 #visit http://bit.ly/1S5nQ4y for reference
183 gpio_config = configparser.ConfigParser()
184 gpio_config.read('gpio.conf')
185 if str(robotID) in gpio_config.sections():
186 config_id = str(robotID)
187 else:
188 config_id = 'default'
189 StepPinForward = int(str(gpio_config[config_id]['StepPinForward']).split(',')[0]),int(str(gpio_config[config_id]['StepPinForward']).split(',')[1])
190 StepPinBackward = int(str(gpio_config[config_id]['StepPinBackward']).split(',')[0]),int(str(gpio_config[config_id]['StepPinBackward']).split(',')[1])
191 StepPinLeft = int(str(gpio_config[config_id]['StepPinLeft']).split(',')[0]),int(str(gpio_config[config_id]['StepPinLeft']).split(',')[1])
192 StepPinRight = int(str(gpio_config[config_id]['StepPinRight']).split(',')[0]),int(str(gpio_config[config_id]['StepPinRight']).split(',')[1])
193
194 GPIO.setmode(GPIO.BOARD)
195 GPIO.setup(StepPinForward, GPIO.OUT)
196 GPIO.setup(StepPinBackward, GPIO.OUT)
197 GPIO.setup(StepPinLeft, GPIO.OUT)
198 GPIO.setup(StepPinRight, GPIO.OUT)
199#Test if user
200if commandArgs.type == "pololu":
201 try:
202 from pololu_drv8835_rpi import motors, MAX_SPEED
203 except ImportError:
204 print "You need to install drv8835-motor-driver-rpi"
205 print "Please install drv8835-motor-driver-rpi for python and restart this script."
206 print "To install: cd /usr/local/src && sudo git clone https://github.com/pololu/drv8835-motor-driver-rpi"
207 print "cd /usr/local/src/drv8835-motor-driver-rpi && sudo python setup.py install"
208 print "Running in test mode."
209 print "Ctrl-C to quit"
210
211if commandArgs.type == 'motozero':
212 GPIO.cleanup()
213 GPIO.setmode(GPIO.BCM)
214
215 # Motor1 is back left
216 # Motor1A is reverse
217 # Motor1B is forward
218 Motor1A = 24
219 Motor1B = 27
220 Motor1Enable = 5
221
222 # Motor2 is back right
223 # Motor2A is reverse
224 # Motor2B is forward
225 Motor2A = 6
226 Motor2B = 22
227 Motor2Enable = 17
228
229 # Motor3 is ?
230 # Motor3A is reverse
231 # Motor3B is forward
232 Motor3A = 23
233 Motor3B = 16
234 Motor3Enable = 12
235
236 # Motor4 is ?
237 # Motor4A is reverse
238 # Motor4B is forward
239 Motor4A = 13
240 Motor4B = 18
241 Motor4Enable = 25
242
243 GPIO.setup(Motor1A,GPIO.OUT)
244 GPIO.setup(Motor1B,GPIO.OUT)
245 GPIO.setup(Motor1Enable,GPIO.OUT)
246
247 GPIO.setup(Motor2A,GPIO.OUT)
248 GPIO.setup(Motor2B,GPIO.OUT)
249 GPIO.setup(Motor2Enable,GPIO.OUT)
250
251 GPIO.setup(Motor3A,GPIO.OUT)
252 GPIO.setup(Motor3B,GPIO.OUT)
253 GPIO.setup(Motor3Enable,GPIO.OUT)
254
255 GPIO.setup(Motor4A,GPIO.OUT)
256 GPIO.setup(Motor4B,GPIO.OUT)
257 GPIO.setup(Motor4Enable,GPIO.OUT)
258#Cytron MDD10 GPIO setup
259if commandArgs.type == 'mdd10' :
260# pwm.setPWMFreq(60)
261 import RPi.GPIO as GPIO
262 GPIO.setmode(GPIO.BCM)
263 GPIO.setwarnings(False)
264 AN2 = 13
265 AN1 = 12
266 DIG2 = 24
267 DIG1 = 26
268 GPIO.setup(AN2, GPIO.OUT)
269 GPIO.setup(AN1, GPIO.OUT)
270 GPIO.setup(DIG2, GPIO.OUT)
271 GPIO.setup(DIG1, GPIO.OUT)
272 time.sleep(1)
273 p1 = GPIO.PWM(AN1, 100)
274 p2 = GPIO.PWM(AN2, 100)
275
276#LED controlling
277if commandArgs.led == 'max7219':
278 spi = spidev.SpiDev()
279 spi.open(0,0)
280 #VCC -> RPi Pin 2
281 #GND -> RPi Pin 6
282 #DIN -> RPi Pin 19
283 #CLK -> RPi Pin 23
284 #CS -> RPi Pin 24
285
286 # decoding:BCD
287 spi.writebytes([0x09])
288 spi.writebytes([0x00])
289 # Start with low brightness
290 spi.writebytes([0x0a])
291 spi.writebytes([0x03])
292 # scanlimit; 8 LEDs
293 spi.writebytes([0x0b])
294 spi.writebytes([0x07])
295 # Enter normal power-mode
296 spi.writebytes([0x0c])
297 spi.writebytes([0x01])
298 # Activate display
299 spi.writebytes([0x0f])
300 spi.writebytes([0x00])
301 columns = [0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8]
302 LEDOn = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]
303 LEDOff = [0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]
304 LEDEmoteSmile = [0x0,0x0,0x24,0x0,0x42,0x3C,0x0,0x0]
305 LEDEmoteSad = [0x0,0x0,0x24,0x0,0x0,0x3C,0x42,0x0]
306 LEDEmoteTongue = [0x0,0x0,0x24,0x0,0x42,0x3C,0xC,0x0]
307 LEDEmoteSuprise = [0x0,0x0,0x24,0x0,0x18,0x24,0x24,0x18]
308 if commandArgs.ledrotate == '180':
309 LEDEmoteSmile = LEDEmoteSmile[::-1]
310 LEDEmoteSad = LEDEmoteSad[::-1]
311 LEDEmoteTongue = LEDEmoteTongue[::-1]
312 LEDEmoteSuprise = LEDEmoteSuprise[::-1]
313
314def SetLED_On():
315 if commandArgs.led == 'max7219':
316 for i in range(len(columns)):
317 spi.xfer([columns[i],LEDOn[i]])
318def SetLED_Off():
319 if commandArgs.led == 'max7219':
320 for i in range(len(columns)):
321 spi.xfer([columns[i],LEDOff[i]])
322def SetLED_E_Smiley():
323 if commandArgs.led == 'max7219':
324 for i in range(len(columns)):
325 spi.xfer([columns[i],LEDEmoteSmile[i]])
326def SetLED_E_Sad():
327 if commandArgs.led == 'max7219':
328 for i in range(len(columns)):
329 spi.xfer([columns[i],LEDEmoteSad[i]])
330def SetLED_E_Tongue():
331 if commandArgs.led == 'max7219':
332 for i in range(len(columns)):
333 spi.xfer([columns[i],LEDEmoteTongue[i]])
334def SetLED_E_Suprised():
335 if commandArgs.led == 'max7219':
336 for i in range(len(columns)):
337 spi.xfer([columns[i],LEDEmoteSuprise[i]])
338def SetLED_Low():
339 if commandArgs.led == 'max7219':
340 # brightness MIN
341 spi.writebytes([0x0a])
342 spi.writebytes([0x00])
343def SetLED_Med():
344 if commandArgs.led == 'max7219':
345 #brightness MED
346 spi.writebytes([0x0a])
347 spi.writebytes([0x06])
348def SetLED_Full():
349 if commandArgs.led == 'max7219':
350 # brightness MAX
351 spi.writebytes([0x0a])
352 spi.writebytes([0x0F])
353
354SetLED_Off()
355
356steeringSpeed = 90
357steeringHoldingSpeed = 90
358
359global drivingSpeed
360
361
362#drivingSpeed = 90
363drivingSpeed = commandArgs.driving_speed
364handlingCommand = False
365
366
367# Marvin
368turningSpeedActuallyUsed = 250
369dayTimeDrivingSpeedActuallyUsed = commandArgs.day_speed
370nightTimeDrivingSpeedActuallyUsed = commandArgs.night_speed
371
372# Initialise the PWM device
373if commandArgs.type == 'motor_hat':
374 pwm = PWM(0x42)
375elif commandArgs.type == 'adafruit_pwm':
376 pwm = PWM(0x40)
377
378# Note if you'd like more debug output you can instead run:
379#pwm = PWM(0x40, debug=True)
380servoMin = [150, 150, 130] # Min pulse length out of 4096
381servoMax = [600, 600, 270] # Max pulse length out of 4096
382armServo = [300, 300, 300]
383
384#def setMotorsToIdle():
385# s = 65
386# for i in range(1, 2):
387# mh.getMotor(i).setSpeed(s)
388# mh.getMotor(i).run(Adafruit_MotorHAT.FORWARD)
389
390
391#if commandArgs.env == 'dev':
392# print 'DEV MODE ***************'
393# print "using dev port 8122"
394# port = 8122
395#elif commandArgs.env == 'prod':
396# print 'PROD MODE *************'
397# print "using prod port 8022"
398# port = 8022
399#else:
400# print "invalid environment"
401# sys.exit(0)
402
403
404if commandArgs.type == 'serial':
405 # initialize serial connection
406 serialBaud = 9600
407 print "baud:", serialBaud
408 #ser = serial.Serial('/dev/tty.usbmodem12341', 19200, timeout=1) # open serial
409 ser = None
410 try:
411 ser = serial.Serial(serialDevice, serialBaud, timeout=1) # open serial
412 except:
413 print "error: could not open serial port"
414 try:
415 ser = serial.Serial('/dev/ttyACM0', serialBaud, timeout=1) # open serial
416 except:
417 print "error: could not open serial port /dev/ttyACM0"
418 try:
419 ser = serial.Serial('/dev/ttyUSB0', serialBaud, timeout=1) # open serial
420 except:
421 print "error: could not open serial port /dev/ttyUSB0"
422 try:
423 ser = serial.Serial('/dev/ttyUSB1', serialBaud, timeout=1) # open serial
424 except:
425 print "error: could not open serial port /dev/ttyUSB1"
426 try:
427 ser = serial.Serial('/dev/ttyUSB2', serialBaud, timeout=1) # open serial
428 except:
429 print "error: could not open serial port /dev/ttyUSB2"
430
431 if ser is None:
432 print "error: could not find any valid serial port"
433 else:
434 telly.sendSettings(ser, commandArgs)
435
436
437
438
439def getControlHostPort():
440
441 url = 'https://%s/get_control_host_port/%s' % (infoServer, commandArgs.robot_id)
442 response = robot_util.getWithRetry(url, secure=commandArgs.secure_cert)
443 return json.loads(response)
444
445def getChatHostPort():
446 url = 'https://%s/get_chat_host_port/%s' % (infoServer, commandArgs.robot_id)
447 response = robot_util.getWithRetry(url, secure=commandArgs.secure_cert)
448 return json.loads(response)
449
450controlHostPort = getControlHostPort()
451chatHostPort = getChatHostPort()
452
453
454
455print "connecting to control socket.io", controlHostPort
456controlSocketIO = SocketIO(controlHostPort['host'], controlHostPort['port'], LoggingNamespace)
457print "finished using socket io to connect to control host port", controlHostPort
458
459if commandArgs.enable_chat_server_connection:
460 print "connecting to chat socket.io", chatHostPort
461 chatSocket = SocketIO(chatHostPort['host'], chatHostPort['port'], LoggingNamespace)
462 print 'finished using socket io to connect to chat ', chatHostPort
463else:
464 print "chat server connection disabled"
465
466if commandArgs.tts_delay_enabled or commandArgs.woot_room != '':
467 userSocket = SocketIO('https://letsrobot.tv', 8000, LoggingNamespace)
468
469print "connecting to app server socket.io"
470appServerSocketIO = SocketIO(infoServer, 8022, LoggingNamespace)
471print "finished connecting to app server"
472
473def setServoPulse(channel, pulse):
474 pulseLength = 1000000 # 1,000,000 us per second
475 pulseLength /= 60 # 60 Hz
476 print "%d us per period" % pulseLength
477 pulseLength /= 4096 # 12 bits of resolution
478 print "%d us per bit" % pulseLength
479 pulse *= 1000
480 pulse /= pulseLength
481 pwm.setPWM(channel, 0, pulse)
482
483
484if commandArgs.type == 'motor_hat' or commandArgs.type == 'adafruit_pwm':
485 pwm.setPWMFreq(60) # Set frequency to 60 Hz
486
487
488WPA_FILE_TEMPLATE = """ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
489update_config=1
490country=GB
491
492network={{
493 ssid=\"beepx\"
494 psk=\"yellow123\"
495 key_mgmt=WPA-PSK
496 }}
497
498network={{
499 ssid=\"{name}\"
500 psk=\"{password}\"
501 key_mgmt=WPA-PSK
502 }}
503"""
504
505
506def isInternetConnected():
507 try:
508 urllib2.urlopen('https://www.google.com', timeout=1)
509 return True
510 except urllib2.URLError as err:
511 return False
512
513def configWifiLogin(secretKey):
514
515 url = 'https://%s/get_wifi_login/%s' % (infoServer, secretKey)
516 try:
517 print "GET", url
518 response = urllib2.urlopen(url).read()
519 responseJson = json.loads(response)
520 print "get wifi login response:", response
521
522 with open("/etc/wpa_supplicant/wpa_supplicant.conf", 'r') as originalWPAFile:
523 originalWPAText = originalWPAFile.read()
524
525 wpaText = WPA_FILE_TEMPLATE.format(name=responseJson['wifi_name'], password=responseJson['wifi_password'])
526
527
528 print "original(" + originalWPAText + ")"
529 print "new(" + wpaText + ")"
530
531 if originalWPAText != wpaText:
532
533 wpaFile = open("/etc/wpa_supplicant/wpa_supplicant.conf", 'w')
534
535 print wpaText
536 print
537 wpaFile.write(wpaText)
538 wpaFile.close()
539
540 say("Updated wifi settings. I will automatically reset in 10 seconds.")
541 time.sleep(8)
542 say("Reseting")
543 time.sleep(2)
544 os.system("reboot")
545
546
547 except:
548 print "exception while configuring setting wifi", url
549 traceback.print_exc()
550
551
552
553
554
555
556
557def incrementArmServo(channel, amount):
558
559 armServo[channel] += amount
560
561 print "arm servo positions:", armServo
562
563 if armServo[channel] > servoMax[channel]:
564 armServo[channel] = servoMax[channel]
565 if armServo[channel] < servoMin[channel]:
566 armServo[channel] = servoMin[channel]
567 pwm.setPWM(channel, 0, armServo[channel])
568
569
570
571def times(lst, number):
572 return [x*number for x in lst]
573
574
575
576def runMotor(motorIndex, direction):
577 motor = mh.getMotor(motorIndex+1)
578 if direction == 1:
579 motor.setSpeed(drivingSpeed)
580 motor.run(Adafruit_MotorHAT.FORWARD)
581 if direction == -1:
582 motor.setSpeed(drivingSpeed)
583 motor.run(Adafruit_MotorHAT.BACKWARD)
584 if direction == 0.5:
585 motor.setSpeed(128)
586 motor.run(Adafruit_MotorHAT.FORWARD)
587 if direction == -0.5:
588 motor.setSpeed(128)
589 motor.run(Adafruit_MotorHAT.BACKWARD)
590
591
592forward = json.loads(commandArgs.forward)
593backward = times(forward, -1)
594left = json.loads(commandArgs.left)
595right = times(left, -1)
596straightDelay = commandArgs.straight_delay
597turnDelay = commandArgs.turn_delay
598#Change sleeptime to adjust driving speed
599#Change rotatetimes to adjust the rotation. Will be multiplicated with sleeptime.
600l298n_sleeptime=0.2
601l298n_rotatetimes=5
602
603
604def handle_exclusive_control(args):
605 if 'status' in args and 'robot_id' in args and args['robot_id'] == robotID:
606
607 status = args['status']
608
609 if status == 'start':
610 print "start exclusive control"
611 if status == 'end':
612 print "end exclusive control"
613
614
615
616def say(message):
617
618 tempFilePath = os.path.join(tempDir, "text_" + str(uuid.uuid4()))
619 f = open(tempFilePath, "w")
620 f.write(message)
621 f.close()
622
623
624 #os.system('"C:\Program Files\Jampal\ptts.vbs" -u ' + tempFilePath) Whaa?
625
626 if commandArgs.festival_tts:
627 # festival tts
628 os.system('festival --tts < ' + tempFilePath)
629 #os.system('espeak < /tmp/speech.txt')
630
631 else:
632 # espeak tts
633 for hardwareNumber in (2, 0, 3, 1, 4):
634 print 'plughw:%d,0' % hardwareNumber
635 if commandArgs.male:
636 os.system('cat ' + tempFilePath + ' | espeak --stdout | aplay -D plughw:%d,0' % hardwareNumber)
637 else:
638 os.system('cat ' + tempFilePath + ' | espeak -ven-us+f%d -s170 --stdout | aplay -D plughw:%d,0' % (commandArgs.voice_number, hardwareNumber))
639
640 os.remove(tempFilePath)
641
642def handle_user_socket_chat_message(args):
643 if args['name'] == 'LetsBot' and args['room'] == commandArgs.woot_room:
644 message = args['message']
645 messageSplit = message.split(' ')
646 if len(messageSplit) == 8:
647 if messageSplit[1] == 'wooted' and messageSplit[3] == 'robits' and messageSplit[4] == 'to' and messageSplit[6] == '!!' and messageSplit[7] == '': # yes.
648 process_woot(messageSplit[0], int(messageSplit[2]))
649
650def process_woot(username, amount): # do stuff with woots here!!
651 print 'woot!! username: ', username, ' amount: ', amount
652
653def handle_chat_message(args):
654 print "chat message received:", args
655
656 if commandArgs.tts_delay_enabled:
657 processing.append(args['_id'])
658 time.sleep(commandArgs.tts_delay_seconds)
659 processing.remove(args['_id'])
660 if args['_id'] in deleted:
661 deleted.remove(args['_id'])
662 print args['_id'] + ' was deleted before TTS played!'
663 exit()
664 else:
665 deleted.remove(args['_id'])
666
667 rawMessage = args['message']
668 withoutName = rawMessage.split(']')[1:]
669 message = "".join(withoutName)
670 urlRegExp = "(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?"
671 if message[1] == ".":
672 exit()
673 elif commandArgs.anon_tts != True and args['anonymous'] == True:
674 exit()
675 elif commandArgs.filter_url_tts == True and re.search(urlRegExp, message):
676 exit()
677 else:
678 say(message)
679
680#MDD10 speed and movement controls
681def moveMDD10(command, speedPercent):
682 if command == 'F':
683 GPIO.output(DIG1, GPIO.LOW)
684 GPIO.output(DIG2, GPIO.LOW)
685 p1.start(speedPercent) # set speed for M1
686 p2.start(speedPercent) # set speed for M2
687 time.sleep(straightDelay)
688 if command == 'B':
689 GPIO.output(DIG1, GPIO.HIGH)
690 GPIO.output(DIG2, GPIO.HIGH)
691 p1.start(speedPercent)
692 p2.start(speedPercent)
693 time.sleep(straightDelay)
694 if command == 'L':
695 GPIO.output(DIG1, GPIO.LOW)
696 GPIO.output(DIG2, GPIO.HIGH)
697 p1.start(speedPercent)
698 p2.start(speedPercent)
699 time.sleep(turnDelay)
700 if command == 'R':
701 GPIO.output(DIG1, GPIO.HIGH)
702 GPIO.output(DIG2, GPIO.LOW)
703 p1.start(speedPercent)
704 p2.start(speedPercent)
705 time.sleep(turnDelay)
706
707
708def moveAdafruitPWM(command):
709 print "move adafruit pwm command", command
710
711 if command == 'L':
712 pwm.setPWM(1, 0, 300) # turn left
713 pwm.setPWM(0, 0, 445) # drive forward
714 time.sleep(0.5)
715 pwm.setPWM(1, 0, 400) # turn neutral
716 pwm.setPWM(0, 0, 335) # drive neutral
717
718 if command == 'R':
719 pwm.setPWM(1, 0, 500) # turn right
720 pwm.setPWM(0, 0, 445) # drive forward
721 time.sleep(0.5)
722 pwm.setPWM(1, 0, 400) # turn neutral
723 pwm.setPWM(0, 0, 335) # drive neutral
724
725 if command == 'BL':
726 pwm.setPWM(1, 0, 300) # turn left
727 pwm.setPWM(0, 0, 270) # drive backward
728 time.sleep(0.5)
729 pwm.setPWM(1, 0, 400) # turn neutral
730 pwm.setPWM(0, 0, 335) # drive neutral
731
732 if command == 'BR':
733 pwm.setPWM(1, 0, 500) # turn right
734 pwm.setPWM(0, 0, 270) # drive backward
735 time.sleep(0.5)
736 pwm.setPWM(1, 0, 400) # turn neurtral
737 pwm.setPWM(0, 0, 335) # drive neutral
738
739
740 if command == 'F':
741 pwm.setPWM(0, 0, 445) # drive forward
742 time.sleep(0.3)
743 pwm.setPWM(0, 0, 345) # drive slowly forward
744 time.sleep(0.4)
745 pwm.setPWM(0, 0, 335) # drive neutral
746 if command == 'B':
747 pwm.setPWM(0, 0, 270) # drive backward
748 time.sleep(0.3)
749 pwm.setPWM(0, 0, 325) # drive slowly backward
750 time.sleep(0.4)
751 pwm.setPWM(0, 0, 335) # drive neutral
752
753 if command == 'S2INC': # neutral
754 pwm.setPWM(2, 0, 300)
755
756 if command == 'S2DEC':
757 pwm.setPWM(2, 0, 400)
758
759 if command == 'POS60':
760 pwm.setPWM(2, 0, 490)
761
762 if command == 'NEG60':
763 pwm.setPWM(2, 0, 100)
764
765
766
767
768
769def moveGoPiGo2(command):
770 if command == 'L':
771 gopigo.left_rot()
772 time.sleep(0.15)
773 gopigo.stop()
774 if command == 'R':
775 gopigo.right_rot()
776 time.sleep(0.15)
777 gopigo.stop()
778 if command == 'F':
779 gopigo.forward()
780 time.sleep(0.35)
781 gopigo.stop()
782 if command == 'B':
783 gopigo.backward()
784 time.sleep(0.35)
785 gopigo.stop()
786
787
788
789
790def changeVolumeHighThenNormal(seconds):
791
792 os.system("amixer -c 2 cset numid=3 %d%%" % 50)
793 time.sleep(seconds)
794 os.system("amixer -c 2 cset numid=3 %d%%" % commandArgs.tts_volume)
795
796
797def maxSpeedThenNormal():
798
799 global maxSpeedEnabled
800
801 maxSpeedEnabled = True
802 print "max speed"
803 time.sleep(120)
804 maxSpeedEnabled = False
805 print "normal speed"
806
807
808
809def handleLoudCommand(seconds):
810
811 thread.start_new_thread(changeVolumeHighThenNormal, (seconds,))
812
813
814def handleMaxSpeedCommand():
815
816 thread.start_new_thread(maxSpeedThenNormal, ())
817
818
819
820def moveGoPiGo3(command):
821 e = easyGoPiGo3
822 if command == 'L':
823 e.set_motor_dps(e.MOTOR_LEFT, -e.get_speed())
824 e.set_motor_dps(e.MOTOR_RIGHT, e.get_speed())
825 time.sleep(0.15)
826 easyGoPiGo3.stop()
827 if command == 'R':
828 e.set_motor_dps(e.MOTOR_LEFT, e.get_speed())
829 e.set_motor_dps(e.MOTOR_RIGHT, -e.get_speed())
830 time.sleep(0.15)
831 easyGoPiGo3.stop()
832 if command == 'F':
833 easyGoPiGo3.forward()
834 time.sleep(0.35)
835 easyGoPiGo3.stop()
836 if command == 'B':
837 easyGoPiGo3.backward()
838 time.sleep(0.35)
839 easyGoPiGo3.stop()
840
841
842
843
844
845def handle_command(args):
846 now = datetime.datetime.now()
847 now_time = now.time()
848 # if it's late, make the robot slower
849 if now_time >= datetime.time(21,30) or now_time <= datetime.time(9,30):
850 #print "within the late time interval"
851 drivingSpeedActuallyUsed = nightTimeDrivingSpeedActuallyUsed
852 else:
853 drivingSpeedActuallyUsed = dayTimeDrivingSpeedActuallyUsed
854
855
856
857 global drivingSpeed
858 global handlingCommand
859
860 if 'robot_id' in args and args['robot_id'] == robotID: print "received message:", args
861 # Note: If you are adding features to your bot,
862 # you can get direct access to incomming commands right here.
863
864
865 if handlingCommand:
866 return
867
868
869
870 #if 'robot_id' in args:
871 # print "args robot id:", args['robot_id']
872
873 #if 'command' in args:
874 # print "args command:", args['command']
875
876
877
878 if 'command' in args and 'robot_id' in args and args['robot_id'] == robotID:
879
880 print('got command', args)
881
882 command = args['command']
883
884 # don't turn set handlingCommand true for
885 # commands that persist for a while and are not exclusive
886 # so others are allowed to run
887 if command not in ("SOUND2", "WALL", "LOUD", "MAXSPEED"):
888 handlingCommand = True
889
890 if command == 'LOUD':
891 handleLoudCommand(25)
892
893 if command == 'MAXSPEED':
894 handleMaxSpeedCommand()
895
896 if commandArgs.type == 'mdd10':
897 if maxSpeedEnabled:
898 print "AT MAX....................."
899 print maxSpeedEnabled
900 moveMDD10(command, 100)
901 else:
902 print "NORMAL................."
903 print maxSpeedEnabled
904 moveMDD10(command, int(float(drivingSpeedActuallyUsed) / 2.55))
905
906 if commandArgs.type == 'adafruit_pwm':
907 moveAdafruitPWM(command)
908
909 if commandArgs.type == 'mebo2':
910 handle_mebo_command(command)
911
912 if commandArgs.type == 'gopigo2':
913 moveGoPiGo2(command)
914
915 if commandArgs.type == 'gopigo3':
916 moveGoPiGo3(command)
917
918 if commandArgs.type == 'owi_arm':
919 owi_arm.handleOwiArm(command)
920
921 if commandArgs.type == 'serial':
922 robot_util.sendSerialCommand(ser, command)
923
924 if commandArgs.type == 'motor_hat' and motorsEnabled:
925 motorA.setSpeed(drivingSpeed)
926 motorB.setSpeed(drivingSpeed)
927 if command == 'F':
928 drivingSpeed = drivingSpeedActuallyUsed
929 for motorIndex in range(4):
930 runMotor(motorIndex, forward[motorIndex])
931 time.sleep(straightDelay)
932 if command == 'B':
933 drivingSpeed = drivingSpeedActuallyUsed
934 for motorIndex in range(4):
935 runMotor(motorIndex, backward[motorIndex])
936 time.sleep(straightDelay)
937 if command == 'L':
938 drivingSpeed = turningSpeedActuallyUsed
939 for motorIndex in range(4):
940 runMotor(motorIndex, left[motorIndex])
941 time.sleep(turnDelay)
942 if command == 'R':
943 drivingSpeed = turningSpeedActuallyUsed
944 for motorIndex in range(4):
945 runMotor(motorIndex, right[motorIndex])
946 time.sleep(turnDelay)
947 if command == 'U':
948 #mhArm.getMotor(1).setSpeed(127)
949 #mhArm.getMotor(1).run(Adafruit_MotorHAT.BACKWARD)
950 incrementArmServo(1, 10)
951 time.sleep(0.05)
952 if command == 'D':
953 #mhArm.getMotor(1).setSpeed(127)
954 #mhArm.getMotor(1).run(Adafruit_MotorHAT.FORWARD)
955 incrementArmServo(1, -10)
956 time.sleep(0.05)
957 if command == 'O':
958 #mhArm.getMotor(2).setSpeed(127)
959 #mhArm.getMotor(2).run(Adafruit_MotorHAT.BACKWARD)
960 incrementArmServo(2, -10)
961 time.sleep(0.05)
962 if command == 'C':
963 #mhArm.getMotor(2).setSpeed(127)
964 #mhArm.getMotor(2).run(Adafruit_MotorHAT.FORWARD)
965 incrementArmServo(2, 10)
966 time.sleep(0.05)
967
968 if commandArgs.type == 'mdd10':
969 turnOffMotorsMDD10()
970
971 if commandArgs.type == 'motor_hat':
972 turnOffMotors()
973 if command == 'WALL':
974 handleLoudCommand(25)
975 os.system("aplay -D plughw:2,0 /home/pi/wall.wav")
976 if command == 'SOUND2':
977 handleLoudCommand(25)
978 os.system("aplay -D plughw:2,0 /home/pi/sound2.wav")
979
980
981 if commandArgs.type == 'l298n':
982 runl298n(command)
983 #setMotorsToIdle()
984 if commandArgs.type == 'motozero':
985 runmotozero(command)
986 if commandArgs.type == 'pololu':
987 runPololu(command)
988
989 if commandArgs.led == 'max7219':
990 if command == 'LED_OFF':
991 SetLED_Off()
992 if command == 'LED_FULL':
993 SetLED_On()
994 SetLED_Full()
995 if command == 'LED_MED':
996 SetLED_On()
997 SetLED_Med()
998 if command == 'LED_LOW':
999 SetLED_On()
1000 SetLED_Low()
1001 if command == 'LED_E_SMILEY':
1002 SetLED_On()
1003 SetLED_E_Smiley()
1004 if command == 'LED_E_SAD':
1005 SetLED_On()
1006 SetLED_E_Sad()
1007 if command == 'LED_E_TONGUE':
1008 SetLED_On()
1009 SetLED_E_Tongue()
1010 if command == 'LED_E_SUPRISED':
1011 SetLED_On()
1012 SetLED_E_Suprised()
1013 handlingCommand = False
1014
1015
1016def runl298n(direction):
1017 if direction == 'F':
1018 GPIO.output(StepPinForward, GPIO.HIGH)
1019 time.sleep(l298n_sleeptime * l298n_rotatetimes)
1020 GPIO.output(StepPinForward, GPIO.LOW)
1021 if direction == 'B':
1022 GPIO.output(StepPinBackward, GPIO.HIGH)
1023 time.sleep(l298n_sleeptime * l298n_rotatetimes)
1024 GPIO.output(StepPinBackward, GPIO.LOW)
1025 if direction == 'L':
1026 GPIO.output(StepPinLeft, GPIO.HIGH)
1027 time.sleep(l298n_sleeptime)
1028 GPIO.output(StepPinLeft, GPIO.LOW)
1029 if direction == 'R':
1030 GPIO.output(StepPinRight, GPIO.HIGH)
1031 time.sleep(l298n_sleeptime)
1032 GPIO.output(StepPinRight, GPIO.LOW)
1033
1034def runmotozero(direction):
1035 if direction == 'F':
1036 GPIO.output(Motor1B, GPIO.HIGH)
1037 GPIO.output(Motor1Enable,GPIO.HIGH)
1038
1039 GPIO.output(Motor2B, GPIO.HIGH)
1040 GPIO.output(Motor2Enable, GPIO.HIGH)
1041
1042 GPIO.output(Motor3A, GPIO.HIGH)
1043 GPIO.output(Motor3Enable, GPIO.HIGH)
1044
1045 GPIO.output(Motor4B, GPIO.HIGH)
1046 GPIO.output(Motor4Enable, GPIO.HIGH)
1047
1048 time.sleep(0.3)
1049
1050 GPIO.output(Motor1B, GPIO.LOW)
1051 GPIO.output(Motor2B, GPIO.LOW)
1052 GPIO.output(Motor3A, GPIO.LOW)
1053 GPIO.output(Motor4B, GPIO.LOW)
1054 if direction == 'B':
1055 GPIO.output(Motor1A, GPIO.HIGH)
1056 GPIO.output(Motor1Enable, GPIO.HIGH)
1057
1058 GPIO.output(Motor2A, GPIO.HIGH)
1059 GPIO.output(Motor2Enable, GPIO.HIGH)
1060
1061 GPIO.output(Motor3B, GPIO.HIGH)
1062 GPIO.output(Motor3Enable, GPIO.HIGH)
1063
1064 GPIO.output(Motor4A, GPIO.HIGH)
1065 GPIO.output(Motor4Enable, GPIO.HIGH)
1066
1067 time.sleep(0.3)
1068
1069 GPIO.output(Motor1A, GPIO.LOW)
1070 GPIO.output(Motor2A, GPIO.LOW)
1071 GPIO.output(Motor3B, GPIO.LOW)
1072 GPIO.output(Motor4A, GPIO.LOW)
1073
1074 if direction =='L':
1075 GPIO.output(Motor3B, GPIO.HIGH)
1076 GPIO.output(Motor3Enable, GPIO.HIGH)
1077
1078 GPIO.output(Motor1A, GPIO.HIGH)
1079 GPIO.output(Motor1Enable, GPIO.HIGH)
1080
1081 GPIO.output(Motor2B, GPIO.HIGH)
1082 GPIO.output(Motor2Enable, GPIO.HIGH)
1083
1084 GPIO.output(Motor4B, GPIO.HIGH)
1085 GPIO.output(Motor4Enable, GPIO.HIGH)
1086
1087 time.sleep(0.3)
1088
1089 GPIO.output(Motor3B, GPIO.LOW)
1090 GPIO.output(Motor1A, GPIO.LOW)
1091 GPIO.output(Motor2B, GPIO.LOW)
1092 GPIO.output(Motor4B, GPIO.LOW)
1093
1094 if direction == 'R':
1095 GPIO.output(Motor3A, GPIO.HIGH)
1096 GPIO.output(Motor3Enable, GPIO.HIGH)
1097
1098 GPIO.output(Motor1B, GPIO.HIGH)
1099 GPIO.output(Motor1Enable, GPIO.HIGH)
1100
1101 GPIO.output(Motor2A, GPIO.HIGH)
1102 GPIO.output(Motor2Enable, GPIO.HIGH)
1103
1104 GPIO.output(Motor4A, GPIO.HIGH)
1105 GPIO.output(Motor4Enable, GPIO.HIGH)
1106
1107 time.sleep(0.3)
1108
1109 GPIO.output(Motor3A, GPIO.LOW)
1110 GPIO.output(Motor1B, GPIO.LOW)
1111 GPIO.output(Motor2A, GPIO.LOW)
1112 GPIO.output(Motor4A, GPIO.LOW)
1113
1114def runPololu(direction):
1115 drivingSpeed = commandArgs.driving_speed
1116 if direction == 'F':
1117 motors.setSpeeds(drivingSpeed, drivingSpeed)
1118 time.sleep(0.3)
1119 motors.setSpeeds(0, 0)
1120 if direction == 'B':
1121 motors.setSpeeds(-drivingSpeed, -drivingSpeed)
1122 time.sleep(0.3)
1123 motors.setSpeeds(0, 0)
1124 if direction == 'L':
1125 motors.setSpeeds(-drivingSpeed, drivingSpeed)
1126 time.sleep(0.3)
1127 motors.setSpeeds(0, 0)
1128 if direction == 'R':
1129 motors.setSpeeds(drivingSpeed, -drivingSpeed)
1130 time.sleep(0.3)
1131 motors.setSpeeds(0, 0)
1132
1133def handleStartReverseSshProcess(args):
1134 print "starting reverse ssh"
1135 appServerSocketIO.emit("reverse_ssh_info", "starting")
1136
1137 returnCode = subprocess.call(["/usr/bin/ssh",
1138 "-X",
1139 "-i", commandArgs.reverse_ssh_key_file,
1140 "-N",
1141 "-R", "2222:localhost:22",
1142 commandArgs.reverse_ssh_host])
1143
1144 appServerSocketIO.emit("reverse_ssh_info", "return code: " + str(returnCode))
1145 print "reverse ssh process has exited with code", str(returnCode)
1146
1147
1148def handleEndReverseSshProcess(args):
1149 print "handling end reverse ssh process"
1150 resultCode = subprocess.call(["killall", "ssh"])
1151 print "result code of killall ssh:", resultCode
1152
1153def onHandleCommand(*args):
1154 thread.start_new_thread(handle_command, args)
1155
1156def onHandleExclusiveControl(*args):
1157 thread.start_new_thread(handle_exclusive_control, args)
1158
1159def onHandleChatMessage(*args):
1160 thread.start_new_thread(handle_chat_message, args)
1161
1162def onHandleUserSocketChatMessage(*args):
1163 thread.start_new_thread(handle_user_socket_chat_message, args)
1164
1165processing = [];
1166deleted = [];
1167def onHandleChatMessageRemoved(*args):
1168 if args[0]['message_id'] in processing and args[0] not in deleted:
1169 deleted.append(args[0]['message_id'])
1170
1171def onHandleAppServerConnect(*args):
1172 print
1173 print "chat socket.io connect"
1174 print
1175 identifyRobotID()
1176
1177
1178def onHandleAppServerReconnect(*args):
1179 print
1180 print "app server socket.io reconnect"
1181 print
1182 identifyRobotID()
1183
1184
1185def onHandleAppServerDisconnect(*args):
1186 print
1187 print "app server socket.io disconnect"
1188 print
1189
1190
1191
1192
1193def onHandleChatConnect(*args):
1194 print
1195 print "chat socket.io connect"
1196 print
1197 identifyRobotID()
1198
1199def onHandleChatReconnect(*args):
1200 print
1201 print "chat socket.io reconnect"
1202 print
1203 identifyRobotID()
1204
1205def onHandleChatDisconnect(*args):
1206 print
1207 print "chat socket.io disconnect"
1208 print
1209
1210def onHandleControlDisconnect(*args):
1211 print
1212 print "control socket.io disconnect"
1213 print
1214 newControlHostPort = getControlHostPort() #Reget control port will start if it closed for whatever reason
1215 if controlHostPort['port'] != newControlHostPort['port']: #See if the port is not the same as before
1216 print "restart: control host port changed"
1217 sys.exit(1) #Auto restart script will restart if the control port is not the same (which is unlikely)
1218
1219#from communication import socketIO
1220controlSocketIO.on('command_to_robot', onHandleCommand)
1221controlSocketIO.on('disconnect', onHandleControlDisconnect)
1222
1223appServerSocketIO.on('exclusive_control', onHandleExclusiveControl)
1224appServerSocketIO.on('connect', onHandleAppServerConnect)
1225appServerSocketIO.on('reconnect', onHandleAppServerReconnect)
1226appServerSocketIO.on('disconnect', onHandleAppServerDisconnect)
1227
1228if commandArgs.tts_delay_enabled:
1229 userSocket.on('message_removed', onHandleChatMessageRemoved)
1230
1231if commandArgs.woot_room != '':
1232 userSocket.on('chat_message_with_name', onHandleUserSocketChatMessage)
1233
1234if commandArgs.enable_chat_server_connection:
1235 chatSocket.on('chat_message_with_name', onHandleChatMessage)
1236 chatSocket.on('connect', onHandleChatConnect)
1237 chatSocket.on('reconnect', onHandleChatReconnect)
1238 chatSocket.on('disconnect', onHandleChatDisconnect)
1239
1240
1241def startReverseSshProcess(*args):
1242 thread.start_new_thread(handleStartReverseSshProcess, args)
1243
1244def endReverseSshProcess(*args):
1245 thread.start_new_thread(handleEndReverseSshProcess, args)
1246
1247appServerSocketIO.on('reverse_ssh_8872381747239', startReverseSshProcess)
1248appServerSocketIO.on('end_reverse_ssh_8872381747239', endReverseSshProcess)
1249
1250#def myWait():
1251# socketIO.wait()
1252# thread.start_new_thread(myWait, ())
1253
1254
1255if commandArgs.type == 'motor_hat':
1256 if motorsEnabled:
1257 # create a default object, no changes to I2C address or frequency
1258 mh = Adafruit_MotorHAT(addr=0x60)
1259 #mhArm = Adafruit_MotorHAT(addr=0x61)
1260
1261
1262def turnOffMotors():
1263 # pi hat motors
1264 mh.getMotor(1).run(Adafruit_MotorHAT.RELEASE)
1265 mh.getMotor(2).run(Adafruit_MotorHAT.RELEASE)
1266 mh.getMotor(3).run(Adafruit_MotorHAT.RELEASE)
1267 mh.getMotor(4).run(Adafruit_MotorHAT.RELEASE)
1268
1269
1270def turnOffMotorsMDD10():
1271 # mdd10 motors
1272 p1.start(0)
1273 p2.start(0)
1274
1275
1276
1277if commandArgs.type == 'motor_hat':
1278 if motorsEnabled:
1279 atexit.register(turnOffMotors)
1280 motorA = mh.getMotor(1)
1281 motorB = mh.getMotor(2)
1282
1283def ipInfoUpdate():
1284 appServerSocketIO.emit('ip_information',
1285 {'ip': subprocess.check_output(["hostname", "-I"]), 'robot_id': robotID})
1286
1287
1288# true if it's on the charger and it needs to be charging
1289def isCharging():
1290 print "is charging current value", chargeValue
1291
1292 # only tested for motor hat robot currently, so only runs with that type
1293 if commandArgs.type == "motor_hat":
1294 print "RPi.GPIO is in sys.modules"
1295 if chargeValue < 99: # if it's not full charged already
1296 print "charge value is low"
1297 return GPIO.input(chargeIONumber) == 1 # return whether it's connected to the dock
1298
1299 return False
1300
1301
1302
1303def sendChargeState():
1304 charging = isCharging()
1305 chargeState = {'robot_id': robotID, 'charging': charging}
1306 appServerSocketIO.emit('charge_state', chargeState)
1307 print "charge state:", chargeState
1308
1309def sendChargeStateCallback(x):
1310 sendChargeState()
1311
1312if commandArgs.type == 'motor_hat':
1313 GPIO.add_event_detect(chargeIONumber, GPIO.BOTH)
1314 GPIO.add_event_callback(chargeIONumber, sendChargeStateCallback)
1315
1316
1317
1318def identifyRobotID():
1319 """tells the server which robot is using the connection"""
1320 print "sending identify robot id messages"
1321 if commandArgs.enable_chat_server_connection:
1322 chatSocket.emit('identify_robot_id', robotID);
1323 appServerSocketIO.emit('identify_robot_id', robotID);
1324
1325
1326def setSpeedBasedOnCharge():
1327 global dayTimeDrivingSpeedActuallyUsed
1328 global nightTimeDrivingSpeedActuallyUsed
1329 if chargeValue < 30:
1330 multiples = [0.2, 1.0]
1331 multiple = random.choice(multiples)
1332 dayTimeDrivingSpeedActuallyUsed = int(float(commandArgs.day_speed) * multiple)
1333 nightTimeDrivingSpeedActuallyUsed = int(float(commandArgs.night_speed) * multiple)
1334 else:
1335 dayTimeDrivingSpeedActuallyUsed = commandArgs.day_speed
1336 nightTimeDrivingSpeedActuallyUsed = commandArgs.night_speed
1337
1338
1339def updateChargeApproximation():
1340
1341 global chargeValue
1342
1343 username = getpass.getuser()
1344 path = "/home/pi/charge_state_%s.txt" % username
1345
1346 # read charge value
1347 # assume it is zero if no file exists
1348 if os.path.isfile(path):
1349 file = open(path, 'r')
1350 try:
1351 chargeValue = float(file.read())
1352 print "error reading float from file", path
1353 except:
1354 chargeValue = 0
1355 file.close()
1356 else:
1357 print "setting charge value to zero"
1358 chargeValue = 0
1359
1360 chargePerSecond = 1.0 / secondsToCharge
1361 dischargePerSecond = 1.0 / secondsToDischarge
1362
1363 if GPIO.input(chargeIONumber) == 1:
1364 chargeValue += 100.0 * chargePerSecond * chargeCheckInterval
1365 else:
1366 chargeValue -= 100.0 * dischargePerSecond * chargeCheckInterval
1367
1368 if chargeValue > 100.0:
1369 chargeValue = 100.0
1370 if chargeValue < 0:
1371 chargeValue = 0.0
1372
1373 # write new charge value
1374 file = open(path, 'w')
1375 file.write(str(chargeValue))
1376 file.close()
1377
1378 print "charge value updated to", chargeValue
1379
1380
1381
1382#setMotorsToIdle()
1383
1384
1385waitCounter = 0
1386
1387
1388
1389if platform.system() == 'Darwin':
1390 pass
1391 #ipInfoUpdate()
1392elif platform.system() == 'Linux':
1393 ipInfoUpdate()
1394
1395
1396lastInternetStatus = False
1397
1398
1399def waitForAppServer():
1400 while True:
1401 appServerSocketIO.wait(seconds=1)
1402
1403def waitForControlServer():
1404 while True:
1405 controlSocketIO.wait(seconds=1)
1406
1407def waitForChatServer():
1408 while True:
1409 chatSocket.wait(seconds=1)
1410
1411def waitForUserServer():
1412 while True:
1413 userSocket.wait(seconds=1)
1414
1415def startListenForAppServer():
1416 thread.start_new_thread(waitForAppServer, ())
1417
1418def startListenForControlServer():
1419 thread.start_new_thread(waitForControlServer, ())
1420
1421def startListenForChatServer():
1422 thread.start_new_thread(waitForChatServer, ())
1423
1424def startListenForUserServer():
1425 thread.start_new_thread(waitForUserServer, ())
1426
1427
1428startListenForControlServer()
1429startListenForAppServer()
1430
1431if commandArgs.enable_chat_server_connection:
1432 startListenForChatServer()
1433
1434if commandArgs.tts_delay_enabled or commandArgs.woot_room != '':
1435 startListenForUserServer()
1436
1437meboDeadCounter = 0
1438def isMeboConnected():
1439 try:
1440 urllib2.urlopen('http://192.168.99.1/ajax/command.json', timeout=1)
1441 return True
1442 except urllib2.URLError as err:
1443 return False
1444
1445while True:
1446 time.sleep(1)
1447
1448 if meboDeadCounter == 10:
1449 meboStatus = isMeboConnected()
1450 if meboStatus:
1451 print "Mebo still reachable."
1452 meboDeadCounter = 0
1453 else:
1454 os.system("sudo killall /bin/bash python ffmpeg")
1455
1456 if (waitCounter % chargeCheckInterval) == 0:
1457 if commandArgs.type == 'motor_hat':
1458 updateChargeApproximation()
1459 sendChargeState()
1460 if commandArgs.slow_for_low_battery:
1461 setSpeedBasedOnCharge()
1462
1463 if (waitCounter % 60) == 0:
1464 if commandArgs.slow_for_low_battery:
1465 if chargeValue < 30:
1466 say("battery low, %d percent" % int(chargeValue))
1467
1468
1469 if (waitCounter % 17) == 0:
1470 if not isCharging():
1471 if commandArgs.slow_for_low_battery:
1472 if chargeValue <= 25:
1473 say("need to charge")
1474
1475
1476 if (waitCounter % 1000) == 0:
1477
1478 internetStatus = isInternetConnected()
1479 if internetStatus != lastInternetStatus:
1480 if internetStatus:
1481 say("ok")
1482 else:
1483 say("missing internet connection")
1484 lastInternetStatus = internetStatus
1485
1486
1487 if (waitCounter % 10) == 0:
1488 if commandArgs.auto_wifi:
1489 if commandArgs.secret_key is not None:
1490 configWifiLogin(commandArgs.secret_key)
1491
1492
1493 if (waitCounter % 60) == 0:
1494 if platform.system() == 'Linux':
1495 ipInfoUpdate()
1496
1497
1498 waitCounter += 1
1499 meboDeadCounter += 1