diff --git a/examples/canbus/README.md b/examples/canbus/README.md new file mode 100644 index 00000000..2de58545 --- /dev/null +++ b/examples/canbus/README.md @@ -0,0 +1,23 @@ +# Using Can Bus as Transport in LIOTA + +LIOTA offers Can bus protocol as transport at Device end via [CanBusDeviceComms](https://github.com/lucifercr07/liota/blob/can_bus/liota/device_comms/canbus_device_comms.py) + +## Using CanBusDeviceComms + +Can bus related parameters required in `send()` and `receive()` like bustype, channel etc., are fetched directly from the user. Please refer this [example](https://github.com/lucifercr07/liota/blob/can_bus/examples/canbus/simulated_canbus.py) for detailed explanation. + +### CanBusMessagingAttributes + +Can bus Messaging attributes allows you to define parameters such as arbitration_id, extended_id etc. which are used in the communication with can bus. + +Currently, using CanBusDeviceComms one can send and receive messages from a can bus. The data can be published over a dcc example graphite. +[example](https://github.com/lucifercr07/liota/blob/can_bus/examples/model_simulated/graphite_canbus_simulated.py) + +#### Default Values: + +* channel, bustype, can_filters and listeners will be **None** +* extende_id will be **True** +* arbitration_id will be **0** and +* dlc will be **None** + +**NOTE:** CanBusMessagingAttributes for a RegisteredMetric object MUST always be passed via **msg_attr** attribute of that RegisteredMetric Object. diff --git a/examples/canbus/simulated_canbus.py b/examples/canbus/simulated_canbus.py new file mode 100644 index 00000000..bdf2544b --- /dev/null +++ b/examples/canbus/simulated_canbus.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# ----------------------------------------------------------------------------# +# Copyright © 2015-2016 VMware, Inc. All Rights Reserved. # +# # +# Licensed under the BSD 2-Clause License (the “License”); you may not use # +# this file except in compliance with the License. # +# # +# The BSD 2-Clause License # +# # +# Redistribution and use in source and binary forms, with or without # +# modification, are permitted provided that the following conditions are met:# +# # +# - Redistributions of source code must retain the above copyright notice, # +# this list of conditions and the following disclaimer. # +# # +# - Redistributions in binary form must reproduce the above copyright # +# notice, this list of conditions and the following disclaimer in the # +# documentation and/or other materials provided with the distribution. # +# # +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"# +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # +# THE POSSIBILITY OF SUCH DAMAGE. # +# ----------------------------------------------------------------------------# + +import time + +from liota.device_comms.canbus_device_comms import CanBusDeviceComms +from liota.entities.metrics.metric import Metric +from liota.lib.transports.CanBus import CanBusMessagingAttributes + +def actuator_value(value): + print value + +def can_connect(id): + msg_attr = CanBusMessagingAttributes(arbitration_id=0x0cf02200+id,extended_id=False) + bus1 = CanBusDeviceComms (bustype='virtual',can_msg_attr=msg_attr) + bus2 = CanBusDeviceComms (bustype='virtual',can_msg_attr=None) + for i in range(5): + bus1.send(data=[id, i, 0, 1, 3, 1, 4, 1],msg_attr=msg_attr) + msg = bus2.receive() + actuator_value(msg) + time.sleep(1) + +if __name__ == "__main__": + for id in range(5): + can_connect(id) + \ No newline at end of file diff --git a/examples/model_simulated/graphite_canbus_simulated.py b/examples/model_simulated/graphite_canbus_simulated.py new file mode 100644 index 00000000..789e5f28 --- /dev/null +++ b/examples/model_simulated/graphite_canbus_simulated.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# ----------------------------------------------------------------------------# +# Copyright © 2015-2016 VMware, Inc. All Rights Reserved. # +# # +# Licensed under the BSD 2-Clause License (the “License”); you may not use # +# this file except in compliance with the License. # +# # +# The BSD 2-Clause License # +# # +# Redistribution and use in source and binary forms, with or without # +# modification, are permitted provided that the following conditions are met:# +# # +# - Redistributions of source code must retain the above copyright notice, # +# this list of conditions and the following disclaimer. # +# # +# - Redistributions in binary form must reproduce the above copyright # +# notice, this list of conditions and the following disclaimer in the # +# documentation and/or other materials provided with the distribution. # +# # +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"# +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # +# THE POSSIBILITY OF SUCH DAMAGE. # +# ----------------------------------------------------------------------------# + +from liota.dcc_comms.socket_comms import SocketDccComms +from liota.dccs.graphite import Graphite +from liota.entities.metrics.metric import Metric +from liota.entities.edge_systems.dell5k_edge_system import Dell5KEdgeSystem +from liota.lib.transports.CanBus import CanBusMessagingAttributes +from liota.entities.devices.canbus_simulated import CanBusSimulated +from liota.lib.utilities.utility import read_user_config + +config = read_user_config('../sampleProp.conf') + +def get_id(): + id = can_model.get_id() + print("Id: ", id) + return id + +if __name__ == "__main__": + edge_system = Dell5KEdgeSystem(config['EdgeSystemName']) + + can_model = CanBusSimulated(name=config['DeviceName'], extended_id=False) + + graphite = Graphite(SocketDccComms(ip=config['GraphiteIP'], + port=config['GraphitePort'])) + + graphite_reg_dev = graphite.register(can_model) + + can_msg_metric = "model.can.id" + + can_msg_id = Metric( + name=can_msg_metric, + unit=None, + interval=1, + sampling_function=get_id + ) + + reg_can_id = graphite.register(can_msg_id) + graphite.create_relationship(graphite_reg_dev, reg_can_id) + reg_can_id.start_collecting() + diff --git a/examples/model_simulated/graphite_thermistor_simulated.py b/examples/model_simulated/graphite_thermistor_simulated.py index acf82674..8cbb1e17 100644 --- a/examples/model_simulated/graphite_thermistor_simulated.py +++ b/examples/model_simulated/graphite_thermistor_simulated.py @@ -132,6 +132,7 @@ def get_thermistor_temperature(): graphite_reg_dev = graphite.register(thermistor_model) metric_name = "model.thermistor.temperature" + thermistor_temper = Metric( name=metric_name, unit=ureg.degC, diff --git a/examples/sampleProp.conf b/examples/sampleProp.conf index 1906d364..fd6e2d31 100644 --- a/examples/sampleProp.conf +++ b/examples/sampleProp.conf @@ -21,5 +21,5 @@ ClientCertFile = None #### [GRAPHITE] #### -GraphiteIP = "Graphite-IP" -GraphitePort = None +GraphiteIP = "92.246.246.188" +GraphitePort = 2003 diff --git a/liota/dccs/graphite.py b/liota/dccs/graphite.py index 24b2ff55..cdb47086 100644 --- a/liota/dccs/graphite.py +++ b/liota/dccs/graphite.py @@ -71,6 +71,7 @@ def _format_data(self, reg_metric): return log.info ("Publishing values to Graphite DCC") log.debug("Formatted message: {0}".format(message)) + print("Message: ", message) return message def set_properties(self, reg_entity, properties): diff --git a/liota/device_comms/canbus_device_comms.py b/liota/device_comms/canbus_device_comms.py new file mode 100644 index 00000000..8f866541 --- /dev/null +++ b/liota/device_comms/canbus_device_comms.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- +# ----------------------------------------------------------------------------# +# Copyright © 2015-2016 VMware, Inc. All Rights Reserved. # +# # +# Licensed under the BSD 2-Clause License (the “License”); you may not use # +# this file except in compliance with the License. # +# # +# The BSD 2-Clause License # +# # +# Redistribution and use in source and binary forms, with or without # +# modification, are permitted provided that the following conditions are met:# +# # +# - Redistributions of source code must retain the above copyright notice, # +# this list of conditions and the following disclaimer. # +# # +# - Redistributions in binary form must reproduce the above copyright # +# notice, this list of conditions and the following disclaimer in the # +# documentation and/or other materials provided with the distribution. # +# # +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"# +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # +# THE POSSIBILITY OF SUCH DAMAGE. # +# ----------------------------------------------------------------------------# + +import logging + +from liota.device_comms.device_comms import DeviceComms +from liota.lib.transports.CanBus import CanBus, CanBusMessagingAttributes +import random + +log = logging.getLogger(__name__) + + +class CanBusDeviceComms(DeviceComms): + """ + DeviceComms for Can bus protocol + """ + + def __init__(self, can_msg_attr, channel=None, can_filters=None, bustype=None, listeners=None): + """ + :param channel: The can interface identifier. Expected type is backend dependent. + :param can_filters:A list of dictionaries each containing a "can_id" and a "can_mask". + >>> [{"can_id": 0x11, "can_mask": 0x21}] + A filter matches, when `` & can_mask == can_id & can_mask`` + :param bustype: The ref:`bus` to listen too. + :param listeners: An iterable of class:`can.Listeners` + :param userdata: userdata is used to store messages coming from the receive channel. + """ + self.channel = channel + if bustype is None: + log.error("Bus Type can't be None") + raise TypeError("Bus Type can't be none") + else: + self.bustype=bustype + self.bustype = bustype + self.can_filters=can_filters + self.listeners = listeners + #self.userdata = Queue.Queue() + if can_msg_attr is None: + log.info("arbitration_id will be auto-generated and extended_id will be true by default") + self.msg_attr = CanBusMessagingAttributes(arbitration_id=random.randint(0,2**29-1),extended_id=True) + elif isinstance(can_msg_attr, CanBusMessagingAttributes): + log.info("User configured arbitration_id and extended_id") + self.msg_attr = can_msg_attr + else: + log.error("can_msg_attr should either be None or of type CanBusMessagingAttributes") + raise TypeError("can_msg_attr should either be None or of type CanBusMessagingAttributes") + self._connect() + + def _connect(self): + self.client = CanBus(self.channel, self.can_filters, self.bustype, self.listeners) + self.client.connect() + + def _disconnect(self): + raise NotImplementedError + + def send(self, data, msg_attr=None): + ''' + :param data(bytearray): data sent to can bus + :param msg_attr : CanMessaging attribute instance + Messages can use extended identifiers, be remote or error frames, and contain data. + ''' + if data is None: + raise TypeError("Data can't be none") + + if msg_attr: + self.client.send(msg_attr.arbitration_id, data, msg_attr.extended_id) + else: + self.client.send(self.msg_attr.arbitration_id, data, self.msg_attr.extended_id) + + def receive(self, timeout=0): + ''' + :param timeout(float): Seconds to wait for a message + ''' + msg = self.client.recv(timeout) + if msg is not None: + return msg + else: + print("No message received") + log.error("No message received") + + def set_filters(self): + self.client.set_filters(self.can_filters) + + def flush_tx_buffer(self): + self.client.flush_tx_buffer() + + def send_periodic(self, data, msg_attr=None, period=0.0, duration=None): + task = self.client.send_periodic(data, msg_attr.arbitration_id, msg_attr.extended_id, period, duration) + #To-Do how the task will be used + + def shutdown(): + self.client.shutdown() + \ No newline at end of file diff --git a/liota/device_comms/device_comms.py b/liota/device_comms/device_comms.py index dc179d83..e48a54ca 100644 --- a/liota/device_comms/device_comms.py +++ b/liota/device_comms/device_comms.py @@ -39,7 +39,6 @@ class DeviceComms: Abstract base class for all device communications. """ __metaclass__ = ABCMeta - #----------------------------------------------------------------------- # If a specific DeviceComms has parameters to establish connection, pass # them to its constructor, not self._connect. Keep self._connect free of diff --git a/liota/entities/devices/canbus_simulated.py b/liota/entities/devices/canbus_simulated.py new file mode 100644 index 00000000..9b064816 --- /dev/null +++ b/liota/entities/devices/canbus_simulated.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# ----------------------------------------------------------------------------# +# Copyright © 2015-2016 VMware, Inc. All Rights Reserved. # +# # +# Licensed under the BSD 2-Clause License (the “License”); you may not use # +# this file except in compliance with the License. # +# # +# The BSD 2-Clause License # +# # +# Redistribution and use in source and binary forms, with or without # +# modification, are permitted provided that the following conditions are met:# +# # +# - Redistributions of source code must retain the above copyright notice, # +# this list of conditions and the following disclaimer. # +# # +# - Redistributions in binary form must reproduce the above copyright # +# notice, this list of conditions and the following disclaimer in the # +# documentation and/or other materials provided with the distribution. # +# # +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"# +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # +# THE POSSIBILITY OF SUCH DAMAGE. # +# ----------------------------------------------------------------------------# + +import threading +import random +from liota.entities.devices.device import Device +from liota.lib.utilities.utility import systemUUID + +class CanBusSimulated(Device): + def __init__(self, name, extended_id=True): + super(CanBusSimulated, self).__init__( + name=name, + entity_id=systemUUID().get_uuid(name), + entity_type="CanBusSimulator" + ) + + self.extended_id=extended_id + self.c1 = 1 #constant to generate different data always + self.data = [1,2,3] + self.arbitration_id=100 + + def get_data(self): + self.c1+=1 + self.data = list(map(lambda x:x+self.c1, self.data)) + return self.data + + def get_id(self): + if self.extended_id is True: + self.arbitration_id=random.randint(0,2**29-1) + else: + self.arbitration_id=random.randint(0,2**11-1) + return self.arbitration_id + diff --git a/liota/lib/transports/CanBus.py b/liota/lib/transports/CanBus.py new file mode 100644 index 00000000..46d309ec --- /dev/null +++ b/liota/lib/transports/CanBus.py @@ -0,0 +1,117 @@ +# -*- coding: utf-8 -*- +# ----------------------------------------------------------------------------# +# Copyright © 2015-2016 VMware, Inc. All Rights Reserved. # +# # +# Licensed under the BSD 2-Clause License (the “License”); you may not use # +# this file except in compliance with the License. # +# # +# The BSD 2-Clause License # +# # +# Redistribution and use in source and binary forms, with or without # +# modification, are permitted provided that the following conditions are met:# +# # +# - Redistributions of source code must retain the above copyright notice, # +# this list of conditions and the following disclaimer. # +# # +# - Redistributions in binary form must reproduce the above copyright # +# notice, this list of conditions and the following disclaimer in the # +# documentation and/or other materials provided with the distribution. # +# # +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"# +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # +# THE POSSIBILITY OF SUCH DAMAGE. # +# ----------------------------------------------------------------------------# + +import logging +import os +import sys +import time +import can +from random import randint + +log = logging.getLogger(__name__) + +class CanBus: + ''' + CAN implementation for LIOTA. It uses python-can internally. + ''' + def __init__(self, channel=None, can_filters=None, bustype=None, listeners=None, bus=None): + + self.channel = channel + self.bustype = bustype + self.can_filters = can_filters + self.listeners = listeners + + def connect(self): + self.bus = can.interface.Bus(bustype=self.bustype, channel=self.channel) + log.info("Connected to Can Bus") + + def send(self, arbitration_id, data, extended_id): + message = can.Message(arbitration_id=arbitration_id, data=data, extended_id=extended_id) + try: + self.bus.send(message) + print("Message sent on {}".format(self.bus.channel_info)) + except can.CanError: + print("Message not sent") + log.error("Message not sent over channel") + + + def recv(self, timeout): + return self.bus.recv(timeout=timeout) + + def set_filters(self): + self.bus.set_filters(self.can_filters) + + def flush_tx_buffer(self): + self.bus.flush_tx_buffer() + + def send_periodic(self, data, arbitration_id, extended_id, period, duration=None): + ''' + :param float period: + Period in seconds between each message + :param float duration: + The duration to keep sending this message at given rate. If + no duration is provided, the task will continue indefinitely. + + :return: A started task instance + :rtype: can.CyclicSendTaskABC + ''' + message = can.Message(arbitration_id=arbitration_id, data=data, extended_id=extended_id) + task = can.send_periodic(message, period, duration) + assert isinstance(task, can.CyclicSendTaskABC) + return task + + def shutdown(self): + self.bus.shutdown() + + def stop(self): + pass + +class CanBusMessagingAttributes: + + def __init__(self, pub_timestamp=0.0, arbitration_id=0, extended_id=True, is_remote_frame=False, + is_error_frame=False, dlc=None): + + self.arbitration_id = arbitration_id + self.extended_id = extended_id + + self.pub_timestamp = pub_timestamp + self.arbitration_id = arbitration_id + self.id_type = extended_id + self.is_remote_frame = is_remote_frame + self.is_error_frame = is_error_frame + + + + + + + \ No newline at end of file diff --git a/tests/test_canbus.py b/tests/test_canbus.py new file mode 100644 index 00000000..eaba0f42 --- /dev/null +++ b/tests/test_canbus.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# ----------------------------------------------------------------------------# +# Copyright © 2015-2016 VMware, Inc. All Rights Reserved. # +# # +# Licensed under the BSD 2-Clause License (the “License”); you may not use # +# this file except in compliance with the License. # +# # +# The BSD 2-Clause License # +# # +# Redistribution and use in source and binary forms, with or without # +# modification, are permitted provided that the following conditions are met:# +# # +# - Redistributions of source code must retain the above copyright notice, # +# this list of conditions and the following disclaimer. # +# # +# - Redistributions in binary form must reproduce the above copyright # +# notice, this list of conditions and the following disclaimer in the # +# documentation and/or other materials provided with the distribution. # +# # +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"# +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # +# THE POSSIBILITY OF SUCH DAMAGE. # +# ----------------------------------------------------------------------------# + +import unittest +import mock +from liota.device_comms.canbus_device_comms import CanBusDeviceComms +from liota.device_comms.device_comms import DeviceComms +from liota.lib.transports.CanBus import CanBusMessagingAttributes + +bus_type = "virtual" + +class TestCanBusDeviceComms(unittest.TestCase): + + + def test_CanBusDeviceComms_fail_without_bustype(self): + with self.assertRaises(Exception): + deviceComms = CanBusDeviceComms("asd") + assertNotIsInstance(deviceComms, CanBusDeviceComms) + + with self.assertRaises(Exception): + deviceComms = CanBusDeviceComms() + assertNotIsInstance(deviceComms, CanBusDeviceComms) + + def test_CanBusDeviceComms_takes_bustype(self): + + deviceComms = CanBusDeviceComms(bustype = bus_type, can_msg_attr=None) + assert isinstance(deviceComms, CanBusDeviceComms) + + def test_CanBusDeviceComms_fail_with_invalidArg_msg_attr(self): + with self.assertRaises(Exception): + deviceComms = CanBusDeviceComms(bustype = bus_type, can_msg_attr="asd") + assertNotIsInstance(deviceComms, CanBusDeviceComms) + + def test_CanBusDeviceComms_pass_with_validArg_msg_attr(self): + mock_can_msg_attr = mock.create_autospec(CanBusMessagingAttributes) + deviceComms = CanBusDeviceComms(bustype = bus_type, can_msg_attr=mock_can_msg_attr) + assert isinstance(deviceComms, CanBusDeviceComms) + + +if __name__ == '__main__': + unittest.main()