Skip to content
23 changes: 23 additions & 0 deletions examples/canbus/README.md
Original file line number Diff line number Diff line change
@@ -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.
55 changes: 55 additions & 0 deletions examples/canbus/simulated_canbus.py
Original file line number Diff line number Diff line change
@@ -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)

70 changes: 70 additions & 0 deletions examples/model_simulated/graphite_canbus_simulated.py
Original file line number Diff line number Diff line change
@@ -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()

1 change: 1 addition & 0 deletions examples/model_simulated/graphite_thermistor_simulated.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions examples/sampleProp.conf
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ ClientCertFile = None

#### [GRAPHITE] ####

GraphiteIP = "Graphite-IP"
GraphitePort = None
GraphiteIP = "92.246.246.188"
GraphitePort = 2003
1 change: 1 addition & 0 deletions liota/dccs/graphite.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the print statements.

return message

def set_properties(self, reg_entity, properties):
Expand Down
122 changes: 122 additions & 0 deletions liota/device_comms/canbus_device_comms.py
Original file line number Diff line number Diff line change
@@ -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 ``<received_can_id> & 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()

1 change: 0 additions & 1 deletion liota/device_comms/device_comms.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
62 changes: 62 additions & 0 deletions liota/entities/devices/canbus_simulated.py
Original file line number Diff line number Diff line change
@@ -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

Loading