Skip to content

Commit 3ab4741

Browse files
committed
Implement a fairly naive sqlite listener and test
1 parent 1aaa4b2 commit 3ab4741

File tree

3 files changed

+76
-7
lines changed

3 files changed

+76
-7
lines changed

can/CAN.py

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from datetime import datetime
1212
import time
1313
import base64
14+
import sqlite3
1415

1516
try:
1617
import queue
@@ -161,17 +162,68 @@ def stop(self):
161162

162163

163164
class SqliteWriter(Listener):
164-
"""TODO"""
165+
"""Logs received CAN data to a simple SQL database.
166+
167+
The sqlite database may already exist, otherwise it will
168+
be created when the first message arrives.
169+
"""
170+
171+
insert_msg_template = '''
172+
INSERT INTO messages VALUES
173+
(?, ?, ?, ?, ?, ?, ?)
174+
'''
165175

166176
def __init__(self, filename):
167-
self.db_file = open(filename, 'wt')
177+
self.db_fn = filename
178+
self.db_setup = False
179+
180+
def _create_db(self):
181+
# Note you can't share sqlite3 connections between threads
182+
# hence we setup the db here.
183+
log.info("Creating sqlite db")
184+
self.conn = sqlite3.connect(self.db_fn)
185+
c = self.conn.cursor()
168186

169187
# create table structure
170-
raise NotImplementedError("TODO")
188+
c.execute('''
189+
CREATE TABLE IF NOT EXISTS messages
190+
(
191+
ts REAL,
192+
arbitration_id INTEGER,
193+
extended INTEGER,
194+
remote INTEGER,
195+
error INTEGER,
196+
dlc INTEGER,
197+
data BLOB
198+
)
199+
''')
200+
self.conn.commit()
201+
202+
self.db_setup = True
171203

172204
def on_message_received(self, msg):
173-
# add row
174-
raise NotImplementedError("TODO")
205+
if not self.db_setup:
206+
self._create_db()
207+
208+
# add row to db
209+
row_data = (
210+
msg.timestamp,
211+
msg.arbitration_id,
212+
msg.id_type,
213+
msg.is_remote_frame,
214+
msg.is_error_frame,
215+
msg.dlc,
216+
msg.data
217+
)
218+
c = self.conn.cursor()
219+
c.execute(SqliteWriter.insert_msg_template, row_data)
220+
221+
self.conn.commit()
222+
223+
def stop(self):
224+
if self.db_setup:
225+
self.conn.commit()
226+
self.conn.close()
175227

176228

177229
class ASCWriter(Listener):

can/interfaces/interface.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ class Bus(object):
1010
"""
1111
Instantiates a CAN Bus of the given `bustype`, falls back to reading a
1212
configuration file from default locations.
13+
14+
:raises: NotImplementedError if the bustype isn't recognized
15+
1316
"""
1417

1518
@classmethod

test/listener_test.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from time import sleep
22
import unittest
33
import random
4-
4+
import logging
5+
import tempfile
56

67
import can
78

8-
import logging
9+
910
logging.getLogger("").setLevel(logging.DEBUG)
1011

1112

@@ -50,6 +51,19 @@ def testBufferedListenerReceives(self):
5051
m = a_listener.get_message(0.2)
5152
self.assertIsNotNone(m)
5253

54+
def testSQLWriterReceives(self):
55+
f = tempfile.NamedTemporaryFile('w')
56+
a_listener = can.SqliteWriter(f.name)
57+
a_listener(generate_message(0xDADADA))
58+
a_listener.stop()
59+
60+
import sqlite3
61+
con = sqlite3.connect(f.name)
62+
c = con.cursor()
63+
c.execute("select * from messages")
64+
msg = c.fetchone()
65+
assert msg[1] == 0xDADADA
66+
5367
def testAscListener(self):
5468
a_listener = can.ASCWriter("test.asc")
5569
notifier = can.Notifier(self.bus, [a_listener], 0.1)

0 commit comments

Comments
 (0)