Skip to content

Commit

Permalink
Add folder
Browse files Browse the repository at this point in the history
  • Loading branch information
Murat Bayram committed Dec 3, 2019
1 parent 6a733d5 commit cb75dae
Show file tree
Hide file tree
Showing 22 changed files with 358 additions and 0 deletions.
8 changes: 8 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM python:3.7-slim-buster
COPY . /app
WORKDIR /app
RUN pip install --upgrade pip
RUN pip install -r requirements
ENTRYPOINT ["python"]
CMD ["status.py"]
CMD ["service.py"]
Binary file added docker/__pycache__/event.cpython-38.pyc
Binary file not shown.
Binary file added docker/__pycache__/listener.cpython-38.pyc
Binary file not shown.
Binary file added docker/__pycache__/mapper.cpython-38.pyc
Binary file not shown.
Binary file added docker/__pycache__/sendData.cpython-38.pyc
Binary file not shown.
Binary file added docker/__pycache__/settings.cpython-38.pyc
Binary file not shown.
17 changes: 17 additions & 0 deletions docker/config.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[Machine]
machineID = 123123123
prefix = Machine/

[MQTT]
broker = URL
port = 1883
user = USER
password = PASSWORD

[C8YMQTT]
tenant = URL
tenantID = TENANTID
port = 1883
user = TENANT/USER
password = PASSWORD
deviceID = DEVICEID
38 changes: 38 additions & 0 deletions docker/event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import logging

import mapper
import settings


class Event(object):

def __init__(self,topic,payload):
self.logger = logging.getLogger('Event')
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
self.logger.debug('Logger for Event was initialised')
self.topic = topic.split('/')
self.logger.info('The following topic arrived %s', self.topic)
self.payload = payload.decode("utf-8").split(',')
self.logger.info('The following topic arrived %s', self.payload)
self.actualParameterName = self.topic[-1]
self.logger.info('The actual parameter name extracted from topic is %s', self.actualParameterName)
self.actualParameterValue = self.payload[0]
self.logger.info('The actual parameter value extracted from payload is %s', self.actualParameterValue)
self.logger.debug('Checking whether Parametername is listed in the parameter file')
if mapper.checkWhetherParameterIsListed(self.actualParameterName) is False:
self.logger.info('Parameter name is not listed inside the parameter file, setting event.valid to false and skipping event')
self.valid = False
return
self.logger.info('Parametername is listed in the parameter file')
self.valid = True
self.logger.debug('Checking whether Paramtername is a Status or else')
self.c8yTopic = 's/us'
if self.actualParameterName == 'Status':
self.logger.info('Paramtername is a Status')
self.c8yPayload = '400,' + str(mapper.getStringfromStatusCode(self.actualParameterValue)) + ',' + str(self.actualParameterValue)
else:
self.actualParameterUnit = self.payload[1]
self.logger.info('Paramtername is a Parameter')
self.c8yPayload = '200,c8y_Data,' + str(self.actualParameterName) + ',' + str(self.actualParameterValue) + ',' + str(self.actualParameterUnit)
self.logger.info('C8yPayload was set inside the Event to %s', self.c8yPayload)
self.logger.info('c8yTopic was set inside the Event to %s', self.c8yTopic)
85 changes: 85 additions & 0 deletions docker/listener.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import paho.mqtt.client as mqtt
import sys
import os
import jsonify
import logging

import sendData
import mapper
import event
import settings

class Listener(object):

def __init__(self):
self.logger = logging.getLogger('Listener')
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
self.logger.debug('Logger for Listener was initialised')
self.Settings = settings
self.logger.debug('Setting machineID variable from config file')
self.machineID = settings.machineID
self.logger.info('MachineID was set to %s', self.machineID)
self.logger.debug('Setting prefix within MQTT broker for machine from config file')
self.prefix = settings.prefix
self.logger.info('Prefix was set to %s', self.prefix)
self.logger.debug('Setting broker for listener from config file')
self.broker = settings.broker
self.logger.info('Broker was set to %s', self.broker)
self.logger.debug('Setting broker port for listener from config file')
self.port = int(settings.port)
self.logger.info('Broker port was set to %s', self.port)
self.logger.debug('Setting user for listener from config file')
self.__user = settings.user
self.logger.info('Broker user was set to %s', self.__user)
self.logger.debug('Setting password for listener from config file')
self.__pw = settings.password
self.logger.info('Broker password was set to %s', self.__pw)
self.logger.debug('Initialising MQTT client with loaded credentials for listener')
self.client = mqtt.Client()
self.logger.info('MQTT client with loaded credentials was initialised')

def on_message_msgs(self,mosq, obj, msg):
#print("Withing Callback")
# This callback will only be called for messages with topics that match
# prefix/machineID/# and will be hand over to event
self.logger.debug('Callback function was initiated')
self.logger.info('The following topic triggered a callback function: %s', msg.topic)
self.logger.info('The following payload arrived: %s', msg.payload)
self.logger.debug('Object with Event-Class will be created')
self.CurrentEvent = event.Event(msg.topic,msg.payload)
self.logger.debug('Object with Event-Class was created')
if self.CurrentEvent.valid is True:
self.logger.info('Event on topic and payload are valid')
self.logger.debug('Creating connector to C8Y´s MQTT')
self.C8YConnector = sendData.MQTTc8yConnector()
self.logger.debug('Connector to C8Y´s MQTT created, Creating SendMQTT to C8Y object and inserting event')
self.C8YSendMQTTData = sendData.SendDataViaMQTT(self.C8YConnector,self.CurrentEvent)
self.logger.debug('Connector to C8Y´s MQTT created, Creating SendMQTT to C8Y object and inserting event')

def start(self):
self.logger.info('Starting listener')
self.topic = str(settings.prefix) + str(settings.machineID) + '/#'
self.logger.info('Listening for callback on all messsages on topic %s: ', self.topic)
self.client.message_callback_add(str(self.topic), self.on_message_msgs)
self.logger.debug('Checking whether user/pw is required')
if len(self.__user) > 0:
self.logger.info('Setting user %s', self.__user)
self.logger.info('Setting password %s', self.__pw)
self.client.username_pw_set(username=self.__user,password=self.__pw)
self.logger.info('Connecting')
self.client.connect(self.broker, self.port, 60)
self.client.subscribe("#", 0)
self.logger.info('Start Loop forever and listening')
self.client.loop_forever()

def stop(self):
self.client.loop_stop()
self.logger.info('Loop forever stopped, disconnecting')
self.client.disconnect()
self.logger.debug('disconnected')


def __del__(self):
self.logger.debug('Deleting Listener Object and stoping loop_forever')
self.client.loop_stop()
self.client.disconnect()
35 changes: 35 additions & 0 deletions docker/mapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import jsonify
import csv
import pandas
import logging

logger = logging.getLogger('Mapper')
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger.debug('Logger for Mapper was initialised')
statuscodesdict = pandas.read_csv('statuscodes.csv',sep=',', header=0, names=['Status','Description'],dtype=str).to_dict(orient='records')
logger.info('Printing Statuscode csv file %s',statuscodesdict)
parametersdict = pandas.read_csv('parameters.csv',sep=',', header=0, names=['Parametername'],dtype=str).to_dict(orient='records')
logger.info('Printing parameter csv file %s',parametersdict)

def getDataFromTopic(topic):
return topic

def getDataFromPayload(payload):
return payload

def getStringfromStatusCode(status):
logger.info('Calling getStringfromStatusCode function with status %s',status)
for dict_ in statuscodesdict:
logger.debug('Looping through statuscodesdict, actual entry is %s',dict_)
logger.debug('Checking whether %s equals %s',dict_, status)
if dict_['Status'] == status:
logger.debug('Returning %s', dict_.get('Description','No Description'))
return dict_.get('Description','No Description')
logger.info('Did not find any Status')
return 0

def checkWhetherParameterIsListed(parameter):
for dict_ in parametersdict:
if dict_['Parametername'] == parameter:
return True
return False
5 changes: 5 additions & 0 deletions docker/parameters.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Parametername
Status
Speed
Force
Temperature
5 changes: 5 additions & 0 deletions docker/requirements
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pandas==0.23.4
Flask==0.10.1
paho-mqtt==1.4.0
jsonify==0.5
numpy==1.16.0
64 changes: 64 additions & 0 deletions docker/sendData.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import paho.mqtt.client as mqtt
import settings
import logging

class SendDataViaMQTT(object):


def __init__(self, MQTTc8yConnector, CurrentEvent):
self.logger = logging.getLogger('sendData')
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
self.logger.debug('Logger for sendData was initialised')
self.MQTTc8yConnector = MQTTc8yConnector
self.c8yTopic = CurrentEvent.c8yTopic
self.logger.info('Current Event created following topic for C8Y Mqtt to create measurement: %s', self.c8yTopic)
self.c8yPayload = CurrentEvent.c8yPayload
self.logger.info('Current Event created following payload for C8Y Mqtt to create measurement: %s', self.c8yPayload)
self.publishSeries()

def publishSeries(self):
self.logger.info('Publishing to C8Y Mqtt')
self.MQTTc8yConnector.client.publish(self.c8yTopic,self.c8yPayload)


class MQTTc8yConnector(object):

def __init__(self):
self.logger2 = logging.getLogger('MQTTc8yConnector')
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
self.logger2.debug('Logger for sendData was initialised')
self.c8yMqttHost = settings.tenant
self.logger2.info('c8yMqtt host was set to %s', self.c8yMqttHost)
self.c8yMqttPort = int(settings.c8yPort)
self.logger2.info('c8yMqtt port was set to %s', self.c8yMqttPort)
self.tenantID = settings.tenantID
self.logger2.info('The tenant ID is %s', self.tenantID)
self.clientID = settings.deviceID
self.deviceID = self.clientID
self.logger2.info('The used clientID for C8Y was set to %s', self.clientID)
self.__c8yUser = settings.c8yUser
self.logger2.info('c8y user was set to %s', self.__c8yUser)
self.__c8yPassword = settings.c8yPassword
self.logger2.info('c8y password was set to %s', self.__c8yPassword)
self.baseTopic = 's/us/'
self.logger2.debug('Calling connect method within MQTTc8yConnectorclass')
self.connect()

def connect(self):
self.logger2.debug('Calling connect method within MQTTc8yConnectorclass')
self.logger2.debug('Initialising MQTT client with loaded credentials for MQTTc8yConnector')
self.client = mqtt.Client(client_id=self.deviceID)
self.logger2.info('MQTT client with loaded credentials was initialised')
self.logger2.info('Setting user/Password')
self.client.username_pw_set(username=self.__c8yUser,password=self.__c8yPassword)
self.logger2.info('Connecting')
self.client.connect(self.c8yMqttHost, self.c8yMqttPort,60)

def disconnect(self):
self.logger2.info('Disconnecting')
self.client.disconnect()
self.logger2.debug('Disconnected')

def __del__(self):
self.logger2.debug('Deleting MQTTC8YConnector Object and disconnecting')
self.disconnect()
44 changes: 44 additions & 0 deletions docker/service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

import urllib.request, json, base64
import os
from datetime import datetime, date, time
from random import randint
from urllib.request import Request
from urllib.request import urlopen
import logging

import listener

logger = logging.getLogger('Service')
logger.debug('Logger for Listener was initialised')

# values provided into environment by cumulocity platform during deployment
C8Y_BASEURL = os.getenv('C8Y_BASEURL')
C8Y_BOOTSTRAP_USER = os.getenv('C8Y_BOOTSTRAP_USER')
C8Y_BOOTSTRAP_TENANT = os.getenv('C8Y_BOOTSTRAP_TENANT')
C8Y_BOOTSTRAP_PASSWORD = os.getenv('C8Y_BOOTSTRAP_PASSWORD')


# result is Base64 encoded "tenant/user:password"
def base64_credentials(tenant, user, password):
str_credentials = tenant + "/" + user + ":" + password
return 'Basic ' + base64.b64encode(str_credentials.encode()).decode()


# subscriber has form of dictionary with 3 keys {tenant, user, password}
def get_subscriber_for(tenant_id):
req = Request(C8Y_BASEURL + '/application/currentApplication/subscriptions')
req.add_header('Accept', 'application/vnd.com.nsn.cumulocity.applicationUserCollection+json')
req.add_header('Authorization', base64_credentials(C8Y_BOOTSTRAP_TENANT, C8Y_BOOTSTRAP_USER, C8Y_BOOTSTRAP_PASSWORD))
response = urlopen(req)
subscribers = json.loads(response.read().decode())["users"]
return [s for s in subscribers if s["tenant"] == tenant_id][0]

try:
logger.info('Starting listener')
Listener = listener.Listener()
Listener.start()
except KeyboardInterrupt:
logger.warning('KeyboardInterrupt was called, stopping listener and raising SystemExit')
Listener.stop()
raise SystemExit
19 changes: 19 additions & 0 deletions docker/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import configparser

config = configparser.ConfigParser()
config.read('config.ini')

broker = config['MQTT']['broker']
port = config['MQTT']['port']
user = config['MQTT']['user']
password = config['MQTT']['password']

machineID = config['Machine']['machineID']
prefix = config['Machine']['prefix']

tenant = config['C8YMQTT']['tenant']
tenantID = config['C8YMQTT']['tenantID']
c8yPort = config['C8YMQTT']['port']
c8yUser = config['C8YMQTT']['user']
c8yPassword = config['C8YMQTT']['password']
deviceID = config['C8YMQTT']['deviceID']
33 changes: 33 additions & 0 deletions docker/status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!flask/bin/python
from flask import Flask, jsonify, request
import mapper

app = Flask(__name__)


@app.route('/health')
def health():
return {'Microservice is up and running'}

app.route('/parameters')
def parameters():
return {parametersdict}


@app.route('/subscriber')
def get_subscriber():
# username has form tenant/user
tenant_id = request.authorization["username"].split('/')[0]
subscriber = get_subscriber_for(tenant_id)
return jsonify(subscriber)


def get_authorization():
tenant_id = request.authorization["username"].split('/')[0]
subscriber = get_subscriber_for(tenant_id)
auth = base64_credentials(subscriber["tenant"], subscriber["name"], subscriber["password"])
return auth


if __name__ == '__main__':
app.run(host='0.0.0.0', port=80, debug=True)
5 changes: 5 additions & 0 deletions docker/statuscodes.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Status,Description
0,Produktion
1,Einmessen
2,Werkzeugwechsel
3,Fehler
Binary file added pics/Dashboard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added pics/config.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added pics/microservice.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added pics/parameters.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added pics/statuscodes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit cb75dae

Please sign in to comment.