-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Murat Bayram
committed
Dec 3, 2019
1 parent
6a733d5
commit cb75dae
Showing
22 changed files
with
358 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Parametername | ||
Status | ||
Speed | ||
Force | ||
Temperature |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Status,Description | ||
0,Produktion | ||
1,Einmessen | ||
2,Werkzeugwechsel | ||
3,Fehler |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.