Repozitář maturitního projektu IVE. Vozítko ovládané přes internet, které sbírá data z modulů.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

250 lines
7.0 KiB

"""
// COMMAND CODES
#define COMMAND_CONTINUE 0x00
#define COMMAND_STOP 0x01
#define COMMAND_RIDE_FORWARD 0x02
#define COMMAND_FORWARD_STEER_LEFT 0x03
#define COMMAND_FORWARD_STEER_RIGHT 0x04
#define COMMAND_RIDE_BACKWARD 0x05
#define COMMAND_BACKWARD_STEER_LEFT 0x06
#define COMMAND_BACKWARD_STEER_RIGHT 0x07
#define COMMAND_TURN_LEFT 0x08
#define COMMAND_TURN_RIGHT 0x09
#define COMMAND_SEND_STATE 0x11
#define COMMAND_SET_PWM_BYTE 0x21
#define COMMAND_SET_SPEED_LEVEL 0x22
#define COMMAND_SET_FREE_SPACE_MULTIPLIER 0x23
// STATE CODES
#define STOP 0x01
#define RIDE_FORWARD 0x02
#define FORWARD_STEER_LEFT 0x03
#define FORWARD_STEER_RIGHT 0x04
#define RIDE_BACKWARD 0x05
#define BACKWARD_STEER_LEFT 0x06
#define BACKWARD_STEER_RIGHT 0x07
#define TURN_LEFT 0x08
#define TURN_RIGHT 0x09
#define BARRIER_IN_FRONT_STOP 0x0A
#define BARRIER_IN_BACK_STOP 0x0B
#define NO_COMMUNICATION_STOP 0x0C
// STATUS CODES
#define OK 0x01
#define ERROR_BARRIER_IN_FRONT 0x02
#define ERROR_BARRIER_IN_BACK 0x03
#define ERROR_UKNOWN 0x11
#define ERROR_NO_VALUE 0x12
"""
import psycopg2, time, pytz, sys
from smbus2 import SMBus
addr = 0x8 # bus address
bus = SMBus(1) # indicates /dev/ic2-1
i2c_commands = {
"COMMAND_CONTINUE" : 0x00,
"COMMAND_STOP" : 0x01,
"COMMAND_RIDE_FORWARD" : 0x02,
"COMMAND_FORWARD_STEER_LEFT" : 0x03,
"COMMAND_FORWARD_STEER_RIGHT" : 0x04,
"COMMAND_RIDE_BACKWARD" : 0x05,
"COMMAND_BACKWARD_STEER_LEFT" : 0x06,
"COMMAND_BACKWARD_STEER_RIGHT" : 0x07,
"COMMAND_TURN_LEFT" : 0x08,
"COMMAND_TURN_RIGHT" : 0x09,
"COMMAND_SEND_STATE" : 0x11,
"COMMAND_SET_PWM_BYTE" : 0x21,
"COMMAND_SET_SPEED_LEVEL" : 0x22,
"COMMAND_SET_FREE_SPACE_MULTIPLIER" : 0x23,
}
status_codes = {
0x01 : "OK",
0x02 : "ERROR_BARRIER_IN_FRONT",
0x03 : "ERROR_BARRIER_IN_BACK",
0x11 : "ERROR_UKNOWN",
0x12 : "ERROR_NO_VALUE",
}
state_codes = {
0x01 : "STOP",
0x02 : "RIDE_FORWARD",
0x03 : "FORWARD_STEER_LEFT",
0x04 : "FORWARD_STEER_RIGHT",
0x05 : "RIDE_BACKWARD",
0x06 : "BACKWARD_STEER_LEFT",
0x07 : "BACKWARD_STEER_RIGHT",
0x08 : "TURN_LEFT",
0x09 : "TURN_RIGHT",
0x0A : "BARRIER_IN_FRONT_STOP",
0x0B : "BARRIER_IN_BACK_STOP",
0x0C : "NO_COMMUNICATION_STOP",
}
def config():
return {
"dbname" : "lucy_main",
"user" : "lucy_primary",
"password" : "lucy1234",
"host" : "localhost",
}
# load list of commands from database
def load_commands():
conn = None
try:
params = config()
conn = psycopg2.connect(**params)
cur = conn.cursor()
cur.execute("SELECT id, system_name FROM app_command ORDER BY id")
rows = cur.fetchall()
except (Exception, psycopg2.DatabaseError) as error:
print("ERROR while loading commands: %s" % error)
rows = []
cur.close()
finally:
if conn is not None:
conn.close()
commands = {}
for key, val in rows:
commands[key] = val
print("Commands loaded..")
print(commands)
return commands
# load commands to be executed from database
def load_commandexecutions(limit=20):
conn = None
try:
params = config()
conn = psycopg2.connect(**params)
cur = conn.cursor()
if limit:
cur.execute("SELECT id, timestamp, command_id, value FROM app_commandexecution WHERE state='Created' ORDER BY id LIMIT %i" % limit)
else:
cur.execute("SELECT id, timestamp, command_id, value FROM app_commandexecution WHERE state='Created' ORDER BY id")
rows = cur.fetchall()
# označí záznam v databázi jako načtený, zbytečně to zatěžuje SD kartu
# for row in rows:
#cur.execute("UPDATE app_commandexecution SET state = %s WHERE id = %s", ("Loaded", row[0]))
# pass
conn.commit()
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print("ERROR while loading command executions: %s" % error)
rows = []
finally:
if conn is not None:
conn.close()
return rows
# set command execution̈́'s state in database to executed
def set_commandexecutions_executed(reports):
conn = None
try:
params = config()
conn = psycopg2.connect(**params)
cur = conn.cursor()
for report in reports:
cur.execute("UPDATE app_commandexecution SET state = %s, result = %s WHERE id = %s", ("Executed", report["result"], report["id"]))
conn.commit()
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print("ERROR while marking command executions as executed: %s" % error)
rows = []
finally:
if conn is not None:
conn.close()
def do_command(command, value=0):
try:
command_code = i2c_commands[command]
if command_code < 0x20:
bus.write_byte(addr, command_code)
# vyhodnocení příkazu někdy trvá trochu déle, zejména kvůli měření vzdálenosti, dáme tedy Micru trochu času
time.sleep(0.05)
else:
bus.write_block_data(addr, command_code, [value])
print("Doing: %s" % command)
return status_codes[bus.read_byte(addr)]
except Exception as e:
print("ERROR while doing command %s: %s" % (command, e))
return "ERROR while doing command %s: %s" % (command, e)
def is_command_execution_valid(ce):
if ce[1] > (time.time() - 2) * 1000: # if timestamp is created not earlier than 2 seconds ago
return True
else:
# if command that should be executed isn't STOP
if ce[2] != 2:
return False
else:
return True
def main():
commands = load_commands()
# mark all command executions created before start as expired
command_executions = load_commandexecutions(limit=None)
reports = []
for ce in command_executions:
reports.append({
"id" : ce[0],
"result" : "ERROR: Primary circuit wasn't available",
})
set_commandexecutions_executed(reports)
while True:
try:
sys.stdout.flush()
command_executions = load_commandexecutions()
reports = []
for ce in command_executions:
try:
if is_command_execution_valid(ce):
result = do_command(commands[ce[2]], ce[3])
else:
print("ERROR: Expired")
result = "ERROR: Expired"
except ValueError as e:
print("ERROR in main loop: %s" % e)
result = "ERROR in primary circuit -> main loop: %s" % e
reports.append({
"id" : ce[0],
"result" : result,
})
set_commandexecutions_executed(reports)
time.sleep(0.05)
except Exception as e:
print(e)
sys.stdout.flush()
if __name__ == '__main__':
main()