Commit dbadb5c1 authored by hackEns's avatar hackEns
Browse files

Fix Jarvis for pgsql

parent 18d7f471
......@@ -12,9 +12,10 @@ Jarvis can be easily installed on a Raspberry Pi, starting from an up-to-date Ra
2. Start the Raspberry Pi. Set it correctly running `sudo raspi-config` (enable camera and so on).
3. Clone Jarvis repo.
4. Run the scripts in `system/` folder to install the requirements.
5. Manually install `wiringPi` for the `gpio` command.
6. Make sure your user is member of the `gpio` and `video` groups.
7. Jarvis does not automatically export the GPIO pins to prevent it from running as `root`. So you should `gpio export PIN out` for the pins you use (1 and 7 by defautl).
7. Run `jarvis.py` and follow the instructions to start Jarvis.
8. Run `jarvis.py` and follow the instructions to start Jarvis.
*Note :* Jarvis requires a MySQL database to be used, and a webserver to serve the web visualisation (repo [Jarvis web](https://github.com/hackEns/Jarvis_web)). As our webserver does not run on the Raspberry Pi, the above scripts do not include the setup for the webserver and the MySQL database. You should install and set them yourself. `system/jarvis.sql` contains all the necessary information to setup the database and tables.
......
......@@ -13,7 +13,7 @@ class Courses(Rule):
if len(args) < 3:
if len(args) == 1:
query = \
"SELECT item, author, date FROM shopping WHERE bought=0"
"SELECT item, author, date FROM shopping WHERE bought=false"
try:
bdd = self.bot.pgsql_connect(serv)
assert(bdd is not None)
......@@ -55,7 +55,7 @@ class Courses(Rule):
"Item déjà présent dans la liste de courses")
return
query = ("INSERT INTO shopping(item, author, comment, date, " +
"bought) VALUES(%s, %s, %s, %s, 0)")
"bought) VALUES(%s, %s, %s, %s, false)")
values = (args[2], author, comment, datetime.datetime.now())
bdd_cursor.execute(query, values)
self.bot.ans(serv, author, "Item ajouté à la liste de courses.")
......@@ -86,7 +86,7 @@ class Courses(Rule):
elif args[1] == "acheté":
query = ("SELECT COUNT(*) as nb FROM shopping WHERE item=%s AND " +
"comment LIKE %s AND bought=0")
"comment LIKE %s AND bought=false")
values = (args[2], '%' + comment + '%')
try:
bdd = self.bot.pgsql_connect(serv)
......@@ -101,8 +101,8 @@ class Courses(Rule):
"Requêtes trop ambiguë. Plusieurs entrées " +
"correspondent.")
return
query = ("UPDATE shopping SET bought=1 WHERE item=%s AND " +
"comment LIKE %s AND bought=0")
query = ("UPDATE shopping SET bought=true WHERE item=%s AND " +
"comment LIKE %s AND bought=false")
bdd_cursor.execute(query, values)
self.bot.ans(serv, author, "Item marqué comme acheté.")
bdd_cursor.close()
......
......@@ -56,9 +56,9 @@ class Emprunt(Rule):
year = this_year
until = datetime.datetime(year, month, day, hour)
query = ("INSERT INTO borrowings" +
"(borrower, tool, `date_from`, until, back)" +
"VALUES (%s, %s, %s, %s, %s)")
values = (borrower, tool, datetime.datetime.now(), until, 0)
"(borrower, tool, date_from, until, back)" +
"VALUES (%s, %s, %s, %s, false)")
values = (borrower, tool, datetime.datetime.now(), until)
try:
bdd = self.bot.pgsql_connect(serv)
assert(bdd is not None)
......@@ -66,7 +66,7 @@ class Emprunt(Rule):
return
bdd_cursor = bdd.cursor()
bdd_cursor.execute("SELECT COUNT(id) FROM borrowings " +
"WHERE back=0 AND borrower=%s AND tool=%s",
"WHERE back=false AND borrower=%s AND tool=%s",
(borrower, tool))
row = bdd_cursor.fetchone()
if row[0] > 0:
......@@ -74,9 +74,9 @@ class Emprunt(Rule):
author,
"Il y a déjà un emprunt en cours, mise à jour.")
query = ("UPDATE borrowings" +
"(id, borrower, tool, `date_from`, until, back)" +
"(id, borrower, tool, date_from, until, back)" +
"SET until=%s " +
"WHERE back=0 AND borrower=%s AND tool=%s")
"WHERE back=false AND borrower=%s AND tool=%s")
values = (until, borrower, tool)
bdd_cursor.execute(query, values)
bdd_cursor.close()
......
......@@ -2,7 +2,7 @@ import re
from ._shared import *
class Emprunt(Rule):
class Retour(Rule):
"""Handles tools borrowings"""
def __init__(self, bot):
......@@ -21,7 +21,7 @@ class Emprunt(Rule):
raise InvalidArgs
else:
borrower = author
query = ("UPDATE borrowings SET back=1 WHERE tool=%s AND borrower=%s")
query = ("UPDATE borrowings SET back=true WHERE tool=%s AND borrower=%s")
values = (args[1], borrower)
try:
bdd = self.bot.pgsql_connect(serv)
......
......@@ -14,8 +14,8 @@ class Update(Rule):
def __call__(self, serv, author, args):
"""Handles bot updating"""
if self.bot.has_admin_rights(serv, author):
subprocess.Popen([self.bot.basepath + "updater.sh",
self.bot.basepath])
subprocess.call([self.bot.basepath + "updater.sh",
self.bot.basepath])
self.bot.ans(serv, author, "I will now update myself.")
self.bot.close()
sys.exit()
......
This diff is collapsed.
<html>
<head>
<title>Log of #hackens IRC channel</title>
<meta charset="utf-8"/>
<link rel="stylesheet" href="/style.css" />
</head>
<body>
<header>
<h1>Log of #hackens IRC channel</h1>
<h2>Day {{day}}</h2>
<p>
<a href="/from/{{start_time_yesterday}}/to/{{end_time_yesterday}}">Previous day</a> <a href="/from/{{start_time_tomorrow}}/to/{{end_time_tomorrow}}">Next day</a>
</p>
</header>
<table>
<tbody>
{{!log}}
</tbody>
</table>
</body>
</html>
#!/usr/bin/env python3
import cgi
import datetime
import os
import re
import sys
from bottle import app, run, route, static_file
nb_colors = 37
if len(sys.argv) < 2:
print("Usage: "+sys.argv[0]+" LOGFILE")
sys.exit(1)
logfile = sys.argv[1]
msg = re.compile('^(\d\d)/(\d\d)/(\d\d\d\d) (\d\d):(\d\d) <(.*?)> (.*)$',)
script_path = os.path.dirname(os.path.realpath(sys.argv[0]))+'/'
def tuple_of_hue(hue):
t = hue * 6.0
if t < 1.0:
return (1.0, t, 0.0)
elif t < 2.0:
return (2.0 - t, 1.0, 0.0)
elif t < 3.0:
return (0.0, 1.0, t - 2.0)
elif t < 4.0:
return (0.0, 4.0 - t, 1.0)
elif t < 5.0:
return (t - 4.0, 0.0, 1.0)
else:
return (1.0, 0.0, 6.0 - t)
def color_of_hue(hue):
c = tuple_of_hue(hue)
return int(((c[0] * 256 + c[1]) * 256 + c[2]) * 255)
def hex_of_color(c):
return '#' + hex(c)[2:].zfill(6)
def hash_color(s, offset=0):
return hex_of_color(color_of_hue(float((sum(s.encode("utf-8")) + offset) % nb_colors) / nb_colors))
colorize_table = {}
def colorize(pseudo):
if pseudo not in colorize_table:
c = hash_color(pseudo)
# vals = list(colorize_table.values())
colorize_table[pseudo] = c
return '<span style="color:%s">%s</span>' % (colorize_table[pseudo], pseudo)
def format_time(t):
short_time = t.strftime('%H:%M')
long_time = t.strftime('%Y-%m-%d %H:%M')
return '<div>%s</div><div class="longtime">%s</div>' % (short_time, long_time)
def format_msg(msg):
msg = cgi.escape(msg)
msg = re.sub('(https?://[^ ]*)', '<a href="\\1">\\1</a>', msg)
return msg
def get_log():
m = []
try:
with open(logfile, 'r') as f:
for l in f.readlines():
m.append(msg.search(l))
except FileNotFoundError:
pass
return m
def write_log(logs_matchs):
write_output = ""
for m in [i for i in logs_matchs if i is not None]:
t = datetime.datetime(int(m.group(3)),
int(m.group(2)),
int(m.group(1)),
int(m.group(4)),
int(m.group(5)))
timestamp = t.timestamp()
write_output += '<tr><td>%s</td><td>&lt;%s&gt;</td><td>%s</td></tr>' % (format_time(t), colorize(m.group(6)), format_msg(m.group(7)))
write_output += "\n"
return write_output
@route("/from/<get_from:int>/to/<get_to:int>", name="from_to", template="index")
def from_to(get_from, get_to):
parsed_log = get_log()
matching_log = []
for m in parsed_log:
t = datetime.datetime(int(m.group(3)),
int(m.group(2)),
int(m.group(1)),
int(m.group(4)),
int(m.group(5)))
if t.timestamp() > get_from and t.timestamp() < get_to:
matching_log.append(m)
now = datetime.datetime.fromtimestamp((get_from + get_to) / 2)
midnight = now.replace(hour=0, minute=0, second=0,
microsecond=0).timestamp()
start_time_yesterday = midnight - 86400
end_time_yesterday = midnight - 1
start_time_tomorrow = midnight + 86400
end_time_tomorrow = midnight + 2*86400 - 1
return {"log": write_log(matching_log),
"start_time_yesterday": int(start_time_yesterday),
"end_time_yesterday": int(end_time_yesterday),
"start_time_tomorrow": int(start_time_tomorrow),
"end_time_tomorrow": int(end_time_tomorrow),
"day": now.strftime("%d/%m/%Y")}
@route("/all", name="all", template="index")
def all():
parsed_log = get_log()
now = datetime.datetime.now()
midnight = now.replace(hour=0, minute=0, second=0,
microsecond=0).timestamp()
start_time_yesterday = midnight - 86400
end_time_yesterday = midnight - 1
start_time_tomorrow = midnight + 86400
end_time_tomorrow = midnight + 2*86400 - 1
return {"log": write_log(parsed_log),
"start_time_yesterday": int(start_time_yesterday),
"end_time_yesterday": int(end_time_yesterday),
"start_time_tomorrow": int(start_time_tomorrow),
"end_time_tomorrow": int(end_time_tomorrow),
"day": now.strftime("%d/%m/%Y")}
@route("/", name="index", template="index")
def index():
now = datetime.datetime.now()
midnight = now.replace(hour=0, minute=0, second=0,
microsecond=0).timestamp()
return from_to(midnight, midnight + 86400 - 1)
@route('/style.css')
def callback():
return static_file('style.css', root='.')
if __name__ == "__main__":
run(host="0.0.0.0", port=8081)
html, body {
margin: 0;
padding: 0;
}
header {
background-color: #ddd;
padding: 0.1em 1em;
margin: 0;
color: #000;
font-family: sans-serif;
}
header h2 {
font-style: italic;
color: #444;
font-weight: normal;
}
td:nth-child(1) {
color: #888;
}
td:nth-child(2) {
font-weight: bold;
color: #888;
padding: 0 1em;
white-space: nowrap;
}
tr:nth-child(2n) {
background-color: #f8f8f8;
}
.longtime {
display: none;
}
td:hover .longtime {
display: block;
color: #eee;
background: #444;
position: absolute;
padding: 0.5em;
border-radius: 0.5em;
}
table {
width: 100%;
font-family: monospace;
}
......@@ -162,7 +162,7 @@ class JarvisBot(ircbot.SingleServerIRCBot):
def pgsql_connect(self, serv):
if self.bdd is None:
try:
self.bdd = psycopg2.connector.connect(**config.get("pgsql"))
self.bdd = psycopg2.connect(**config.get("pgsql"))
self.bdd.set_isolation_level(0) # Set autocommit
except psycopg2.Error as err:
if config.get("debug"):
......@@ -173,7 +173,7 @@ class JarvisBot(ircbot.SingleServerIRCBot):
elif err.errno == psycopg2.errorcode.ER_BAD_DB_ERROR:
serv.say("La base PostgreSQL n'existe pas.")
return None
elif not self.bdd.is_connected():
elif self.bdd.closed > 0:
self.bdd.reconnect()
return self.bdd
......
......@@ -75,8 +75,6 @@ class Config():
# Pins, uses BCM numbering
self.set("pin1_cam", 18) # To control the camera servo, PWM
self.set("pin2_cam", 18) # To control the second camera servo, PWM
self.set("pin_atx", 4) # To control the ATX status via green wire
self.set("pin_atx_status", 17) # 5V, to get ATX status
# RX/TX path in the filesystem to communicate with LED
self.set("pin_led", "")
# Access control
......
......@@ -28,10 +28,6 @@ then
screen -dmS jarvis
# Jarvis lui-même
screen -S jarvis -p 0 -X stuff "~/Jarvis/jarvis.py$(printf \\r)"
# Les logs de Jarvis
screen -S jarvis -X screen
screen -S jarvis -p 1 -X stuff "~/Jarvis/irclog/irclog.py ~/Jarvis/data/jarvis.all.log$(printf \\r)"
else
su jarvis -c "$0"
fi
......@@ -8,7 +8,7 @@ apt-get --yes purge x11-common lxde dillo gnome-icon-theme \
libx11-data libx11-xcb1 desktop-file-utils debian-reference-en \
debian-reference-common java-common
apt-get --yes install postgresql-client libpq-dev supervisor
apt-get --yes install postgresql-client libpq-dev supervisor vim screen autossh ack-grep
# Remove unused packets
apt-get --yes autoremove --purge
......
......@@ -16,7 +16,4 @@ else
echo "Erreur durant la mise à jour"
fi
echo "Lancement de jarvis"
screen -x jarvis -p 0 -X stuff $1"/jarvis.py$(printf \\r)"
exit 0
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment