• Non ci sono risultati.

Design and development of a cloud based serverless architecture for industrial iot.

N/A
N/A
Protected

Academic year: 2021

Condividi "Design and development of a cloud based serverless architecture for industrial iot."

Copied!
81
0
0

Testo completo

(1)

UNIVERISTÀ DEGLI STUDI DI PISA

Facoltà di Scienze, Matematiche, Fisiche e Naturali

Corso di laurea magistrale in Computer Science

Master Thesis

Design and development of a cloud based serverless architecture for industrial IoT

Supervisors

Prof. Daniele Mazzei Prof. Stefano Chessa

Student Andrea Lisi 523680 YEAR 2017-18

(2)
(3)

2

Table of Content

Table of Content ... 2

1 - Introduction ... 5

2 - Architecture ... 8

2.1 – Amazon Web Services ... 10

2.1.1 – IoT Core ... 11

2.1.2 – Simple Queue Service ... 13

2.1.3 – Relational Database Service ... 15

2.1.4 – S3 ... 15

2.1.5 – Elastic Compute Cloud ... 16

2.1.6 – Simple Email Service ... 16

2.1.7 - Lambda ... 17 2.2 - Web Server ... 34 2.2.1 - Tornado framework ... 35 2.2.2 - Nginx ... 46 2.2.3 - Docker ... 48 2.3 - Database Postgresql ... 52

2.4 – Design and development of a generic industrial IoT firmware for the 4ZeroBox device ... 56

2.4.1 - 4ZeroBox ... 56

2.4.2 - Zerynth ... 59

2.4.3 - Generic Firmware Architecture ... 61

3 - Provisioning ... 68

3.1 - AWS provisioning ... 68

(4)

3

4 – Firmware Over the Air Update ... 71

4.1 - AWS jobs ... 71

4.2 - Zerynth fota ... 72

5 - Conclusions ... 75

Bibliography ... 78

(5)
(6)

5

1 - Introduction

Internet of things (IoT) is a term indicating a nowadays conception of interconnected autonomous devices, technologies, networks, human resources, each of which collects and shares data. This is not just new in computer science: exchanging data fastly between long distance hosts has been a principal purpose in developing machine’s networks during the early days of internet. Differences nowadays are related to several aspects: the transition from analogic to digital technology, enabled the developing of a modern family of devices programmable via software; these devices became to be equipped by sensors to percept the environment; connectivity (bluethoot, WIFI, GPS, …) gave them the ability to communicate each other. Thanks to the presence of customizable software inside, we can talk about a kind of intelligence these devices have, and it permits them be autonomous node in the network. Almost all everyday objects are becoming “smart”, just thinking about mobile phones or wristwatches, which have added features not exactly typical of their original function.

A common example of an IoT application is in the home automation field, where a washing machine and a dishwasher talk together to decide which one should start/stop based on the power consumption limit. In the same way, other connected devices can communicate their need of resources, allowing automatic system balancing within certain limits.

IoT is also having impact on industries, that is the use of that technologies in the production and transportation sectors to create intelligent, self-regulating production systems and environments. For any company that deals with the production and/or transportation of physical assets, the IoT

(7)

6 can generate revolutionary operating efficiencies. Machines capable of processing and interpreting data enable automated production processes with the flexibility to adapt on-the-fly, to changing conditions and new data. These machines can also determine when they need maintenance operations and sometimes execute them automatically: in this way, it is possible to avoid failures and relative downtime, increasing production, capacity and overall productivity.

As a counterpart, the spread of IoT devices in all contexts (home, companies, production plants, public administrations, public services, hospitals, etc.), raises a very important security issue. In the last three years, about one in five companies has suffered at least one attack on their IoT environments. Therefore, the risk is no longer just on servers or mobile devices, but on the huge amount of intelligent objects that collect data and which increasingly contribute to governing our buildings, our production and departments on which mobility services depend. It is clear that the risks are certainly not inferior if a hacker focused on IoT, can block a production plant or violate access and security systems of a series of buildings.

This thesis comes out from concepts previously mentioned, specifically it wants to describe a generic IoT system implementation that monitors industrial machines. In any kind of industries there is something that should be monitored, this task is often delegated to human being that is easily prone to error, and some of them could be costly for companies. Imaging a company that produces meat and keeps it in cold storage, what happens if they have a malfunction and the temperatures are altered? This could cause a serious loss for the company, not mentioning the waste!

(8)

7 This system is based on the interaction of different actors/platforms, specifically there are devices called 4ZeroBox, which get data from industrial machines and send them to Amazon Cloud Services (AWS), which provides many micro-services, easy to set up and that are able to interact each other. It includes also a web server, to let users visualize data and receive advices.

The first chapter of this thesis starts arguing about the architecture, initially describing each AWS service used and their function within the system, concluding with a complete view of the cloud architecture and the access policies necessary for these services to communicate each other and with the outside world. It continues with a complete description of web server architecture including languages, frameworks and libraries used. The last section regards 4ZeroBox devices and the Zerynth platform to program them, it concentrate on the generic firmware architecture that runs on them.

The second chapter regards device provisioning, arguing about security authentication on AWS, how this is implemented with Zerynth and 4ZeroBox during the installation phase.

In the last chapter the mechanism used to update the device’s firmware is discussed. Every time a new patch is released, the firmware over the air update (FOTA) process – used to send a remote update – begins, the chapter also consider how this functionality is supported by Zerynth and AWS services.

The purpose of this thesis, is to give a generic and distributed IoT system for industries, to improve production, reduce loss and have a complete view of the state of the machines through real time monitoring.

(9)

8

2 - Architecture

The idea of this project is to collect data from devices, and let them be available to users in an understandable format like graphs. In the very beginning, the system architecture can be summarized as constituted by three main actors/technologies:

 Devices, which collect data from industrial machine’s sensors and/or PLCs, execute some basic computation and sends results to the “Data Collector”;

 Amazon Web Services, which is the real core of the application: its job consists in receiving data from devices, store them into a database, manage user’s requests to visualize data, other service operations to maintain the system.

 Users are clients who wants to visualize data and to be notified in real time if something goes wrong.

(10)

9 Device’s job is not only related to monitoring, they are also able to receive messages, to update the firmware and general requests used to know its state; it only needs power and a network connection.

AWS can be called the “core” of the system, because it maintains a set of services, which manage all data coming from devices and organizes them in a database. It deals with device authentication and periodically database maintenance, sending appropriate alerts to the administrator in case of problems. It also elaborate requests coming from users and give them appropriate data in real time, send periodically reports in different format and advice through alarms if some value goes outside a predefined threshold.

Users are the ones who benefit from this system, they can visualize data in a readable format and based on the type, they have access to different views of the machines.

(11)

10

2.1 – Amazon Web Services

Going deeper into AWS core part, there are many micro-services that are useful to makes the entire application easy to maintain, auto-scalable, efficient with a large number of devices and users and requires low effort to build up.

IoT service manage devices connection and data flow; Relational Database Service (RDS) builds up a database instance to store data; Elastic Computing Cloud (EC2) service is where the web server resides; they make up the basic structure of the cloud architecture.

FIGURE 2:GENERIC CLOUDARCHITECTURE FIGURA 1

(12)

11

2.1.1 – IoT Core

Amazon provides a complete IoT service and according to the AWS documentation, it is described as follow:

“AWS IoT provides secure, bi-directional communication between Internet-connected devices such as sensors, actuators, embedded micro-controllers, or smart appliances and the AWS Cloud. This enables you to collect telemetry data from multiple devices, and store and analyze the data. […].

AWS IoT consists of the following components:

 device gateway: enables devices to securely and efficiently communicate with AWS IoT;

 message broker: provides a secure mechanism for devices and AWS IoT applications to publish and receive messages from each other. You can use either the MQTT protocol directly or MQTT over WebSocket to publish and subscribe. You can use the HTTP REST interface to publish;

 rules engine: provides message processing and integration with other AWS services. You can use an SQL-based language to select data from message payloads, and then process and send the data to other services […];

 security and Identity service: provides shared responsibility for security in the AWS Cloud. Your devices must keep their credentials safe in order to securely send data to the message broker. The message broker and rules engine use AWS security features to send data securely to devices or other AWS services.

(13)

12  Registry and Group registry: Organizes the resources associated

with each device in the AWS Cloud […].

 Device shadow: a JSON document used to store and retrieve current state information for a device.

 Device Provisioning service: allows you to provision devices using a template that describes the resources required for your device. [… ] Devices use certificates to authenticate with AWS IoT. Policies determine which operations a device can perform in AWS IoT.  Custom Authentication service: you can define custom authorizers

that allow you to manage your own authentication and authorization strategy using a custom authentication service and a Lambda function.

 Jobs service: allows you to define a set of remote operations that are sent to and executed on one or more devices connected to AWS IoT. [… ]”

As described above, the IoT service has an endpoint at which each device must authenticate before sending data, therefore devices have their private (or shared) ‘signature’ to show at the entry point. After the authentication, the policy document associated to its certificate is evaluated to extract access permissions, such as the MQTT topic to publish allowed or other AWS services to interact. Finally, an action can be defined to specify what to do with incoming data.

In this system, IoT is the entry point of data coming from devices, each message contains data in JSON format that are manipulated by a rule in an SQL-like syntax, which is triggered each time an MQTT message arrive.

(14)

13 In this case the rule defined, puts a timestamp on incoming messages, which is managed later in the system. The action specified takes incoming messages and sends them to a queue defined in SQS service.

2.1.2 – Simple Queue Service

AWS defines SQS service as follow:

“Amazon Simple Queue Service (Amazon SQS) offers a secure, durable, and available hosted queue that lets you integrate and decouple distributed software systems and components. […] Amazon SQS supports both standard and FIFO queues. Main benefits:

Security – you control who can send messages to and receive messages from an Amazon SQS queue […].

Durability – To ensure the safety of your messages, Amazon SQS stores them on multiple servers. […]

Availability – Amazon SQS uses redundant infrastructure to provide highly-concurrent access to messages and high availability for producing and consuming messages.

Scalability – Amazon SQS can process each buffered request independently, scaling transparently to handle any load increases or spikes without any provisioning instructions.

Reliability – Amazon SQS locks your messages during processing, so that multiple producers can send and multiple consumers can receive messages at the same time. […]”

(15)

14 The introduction of a message queue service, allows asynchronous communication, through which the producer and consumer endpoints of messages, interact with the queue and not between them. Producers can add requests to the queue without having to wait for them to be processed. Consumers retrieve messages only if they are available. No component of the system is ever idle and waiting for the actions of another component, so the data flow is optimized. Queues make data persistent and reduce errors that occur when portions of the system are offline. Separating the different components with message queues also allow greater fault tolerance.

In this system, a SQS standard queue is instantiated because it supports a nearly unlimited number of transaction per seconds per action and at-least-once message delivery, namely AWS ensures that messages are generally delivered in the same order as they arrive, but more than one copy might be delivered out of order.

The queue introduction after IoT service is due to several need such as improve scalability of the system,avoid loss of messages; Amazon stores copies of incoming messages in multiple server for redundancy and high availability, sometimes one of these server might be unavailable and copy of messages are not deleted and there can be duplicate when they are delivered. This problem cannot be avoided at this level, rather it is managed directly in the database.

(16)

15

2.1.3 – Relational Database Service

A small extract of the AWS documentation explains that:

“Amazon Relational Database Service (Amazon RDS) is a web service that makes it easier to set up, operate, and scale a relational database in the cloud. It provides cost-efficient, resizable capacity for an industry-standard relational database and manages common database administration tasks. Amazon RDS takes over many of the difficult or tedious management tasks of a relational database: easy increment of resources, automatic backups manage, […] ”

AWS concept of DB instance is an isolate environment in the cloud, which can contain multiple databases. Each DB instance runs a DB engine and it can be instantiated on a private network using Amazon Virtual Private Cloud (VPC) service. In that way it is possible to have control over the virtual network environment selecting the IP address range, creating subnets and configuring routing access control list.

Messages in the queue, are then managed by a function defined in AWS Lambda service and inserted into a RDS PostgreSQL database.

2.1.4 – S3

Amazon Simple Storage Service (Amazon S3) is storage for the Internet. According to AWS documentation, it is possible to use Amazon S3 to store and retrieve any amount of data at any time, from anywhere on the web.

S3 stores data as objects within buckets. An object consists of a file and optionally any metadata that describes that file. Buckets are containers for objects. For each bucket, is possible to control access to it (who can create,

(17)

16 delete, and list objects in the bucket), view access logs for it and its objects.

In this thesis S3 is used as container for database dumps and for now device’s firmware. Each predefined time period, old data is removed from database to lighten its weight and they are stored in a bucket to maintain a data history.

2.1.5 – Elastic Compute Cloud

Amazon Elastic Compute Cloud (EC2) provides scalable computing capacity in the Amazon Web Services (AWS) cloud. It eliminates the need to invest in hardware up front, so to develop and deploy applications faster. It allows to launch as many virtual servers as needed, configure security and networking, and manage storage. EC2 uses public–key cryptography to encrypt and decrypt login information. When an instance is launched, a public IP aggress is assigned unless otherwise specified. In this thesis, EC2 is used to instantiate the web server, accessible through public IP address.

2.1.6 – Simple Email Service

Amazon SES is an email platform that provides an easy, cost-effective way to send and receive email using your own email addresses and domains.

SES is used in this project as a communication service for users, regarding information about alarms and reports, it is managed by an AWS Lambda function.

(18)

17

2.1.7 - Lambda

Amazon Web Services official site gives the following definition for Lambda:

“AWS Lambda is a compute service that lets you run code without provisioning or managing servers. AWS Lambda executes your code only when needed and scales automatically, from a few requests per day to thousands per second. With AWS Lambda, you can run code for virtually any type of application or backend service - all with zero administration. AWS Lambda runs your code on a high-availability compute infrastructure and performs all of the administration of the compute resources, including server and operating system maintenance, capacity provisioning and automatic scaling, code monitoring and logging. […] AWS Lambda is an ideal compute platform for many application scenarios, provided that you can write your application code in languages supported by AWS Lambda (that is, Node.js, Java, Go and C# and Python), and run within the AWS Lambda standard runtime environment and resources provided by Lambda. AWS Lambda manages the compute fleet that offers a balance of memory, CPU, network, and other resources.”

In this architecture, the Lambda service is widely used because of its flexibility and low cost and lets AWS services interact each other. The language used for functions is Python 3.6 and each lambda consists of a handler function, which is the one called at each run, and possibly other functions/library to support handlers and to let them more readable. Basically, all lambda interact with database, then they are supported by a psycopg2 library in their package for Postgresql DB engine.

(19)

18 AWS allows the definition of environment variables in the Lambda function’s scope, it guarantees such variables have visibility only in the machine instance where the lambda is performed. This functionality is used to set database credentials, buckets name, queue references and other starting information needed to initialize the function.

CODE 1: LAMBDA INITIALIZATION

In the code above, the lambda function gets database credential and SQS queue URI, initialize connection and the AWS SQS service; that code is almost the same in all lambda functions used in this system, the differences are related only on the AWS services they initialize, depending on which of them they interact with.

(20)

19 First lambda defined is called ingestion, its job regards extracting messages from queue and putting them into RDS database, therefore it has the consumer role for the queue.

FIGURE 3: INGESTION LAMBDA FUNCTION

There are basically two ways to execute ingestion to manage tasks in a queue:

 Amazon SQS enables trigger function which are executed every time a new task arrive in a queue;

(21)

20

 Amazon CloudWatch is a monitoring and management service created for system operator. It is possible to create a CloudWatch Event which executes a Lambda function at every predefined time interval.

Using trigger function, each message is managed instantly, CloudWatch events instead allows to manage a set of messages together, saving up lambda calls. In both case there must be a mechanism to handle incoming messages when the database is down and the flow of data stops in a lambda function.

In this thesis, the CloudWatch event method is used because the trigger function has been introduced by AWS after the developing period.

def handler(event, context): db.cursor() rtime = context.get_remaining_time_in_millis() item_count = 0 qq = AWS.SQS(sqs_url) data = DB.Data(metrics) while rtime>2000: messages = qq.messages() if not messages:

info("SQS seems empty") break

# now build the query

data.clear()

for message in messages: if data.append(message): qq.mark(message) else:

warning("Malformed message",message) try:

data.insert()

item_count+=len(data.values)

info("inserted",item_count,"items") except Exception as e:

error("Failed insert",e) qq.clear()

(22)

21 else:

# messages inserted, delete from queue

qq.sweep()

rtime = context.get_remaining_time_in_millis() return item_count

CODE 2: INGESTION LAMBDA FUNCTION

When the handler is called, the function reads a bag of messages from the queue and tries to insert them into the database; if the operation has success, it deletes that messages into the queue, else it only clear the local list. In that way all messages will be stored soon or later.

As previously mentioned, Lambda is also used for database management: each day, a CloudWatch event invokes a lambda function called dbmanager to delete old tables, store data in an S3 bucket and create new daily tables.

CODE 3: DBMANAGER LAMBDA INITIALIZATION info("Lambda starting up")

try:

# gather db info from env variables

dbname = os.environ["DB_NAME"] user = os.environ["DB_USER"] passwd = os.environ["DB_PASS"] dbhost = os.environ["DB_HOST"] cid = os.environ["SOLUTION"]

max_days = int(os.environ["MAX_RETENTION_DAYS"]) bucket_name = os.environ["STORE_BUCKET"]

metrics = os.environ["METRICS"].split(",") if len(metrics)<=0:

raise Exception("Bad metrics")

# num_metrics = int(os.environ["NUM_METRICS"])

except Exception as e:

(23)

22 In the initialization phase, the function retrieves from environment variables the S3 bucket name, the number of days a table must remain into database and data metrics.

def handler(event, context): tables = db.tables("day_") tables.sort()

if len(tables)>0: oldest = tables[0] newest = tables[-1]

info("cool tables",oldest,newest) now = utcnow()

today_datetime = now.isoformat(sep=" ")

today_date = today_datetime[:10] # extract date

today_datetime = today_date+" 00:00:00" tomorrow = utcnow(days=1) tomorrow_datetime = tomorrow.isoformat(sep=" ") tomorrow_date = tomorrow_datetime[:10] tomorrow_datetime = tomorrow_date+" 00:00:00" t2 = utcnow(days=2) t2_datetime = t2.isoformat(sep=" ") t2_date = t2_datetime[:10] t2_datetime = t2_date+" 00:00:00"

today_table = "day_"+today_date.replace("-","_")

tomorrow_table = "day_"+tomorrow_date.replace("-","_")

CODE 4: DMBMANAGER LAMBDA HANDLER (FIRST PART)

The handler function retrieves the list of all tables that starts with “days_”, prepares and create the day after table. If such operation fails, the function sends an email and/or sms to the system administrator using Amazon SES service.

(24)

23 if today_table not in tables:

try:

info("Creating today table",today_datetime,tomorrow_datetime)

data.data_provisioning(today_table,today_datetime,tomorrow_datetime) info("Today table created")

except Exception as e:

error("Failed today creation of table!",e) ses.send()

if tomorrow_table not in tables: try:

info("Creating tomorrow table",tomorrow_datetime,t2_datetime)

data.data_provisioning(tomorrow_table,tomorrow_datetime,t2_datetime) info("Tomorrow table created")

except Exception as e:

error("Failed daily creation of tables!",e) ses.send()

if len(tables)<=max_days:

info("No cleaning required") return

#list existing dumps

dump_path = "data/"+oldest+"/" dumps = s3.ls(dump_path) info("Current dumps",dumps) hh=0

if not dumps:

# create store for the day

info("Creating store") s3.mkdir(dump_path) hh = max(len(dumps)-2,0)

oldest_datetime = utcdate(isodate=oldest[4:].replace("_","-"))

CODE 5: DBMANAGER LAMBDA (SECOND PART)

In the second part, the header function checks if today_table and tomorrow_table have been created and if the oldest one has been stored in a bucket, if not it does.

(25)

24 if hh==24:

# all dumps done, drop table

info("All dumps done") return

info("Let's start dumping from hour",hh) # start dumping

# [additional code to create and store csv files] # deleting old tables

try:

db.drop(oldest) except Exception as e: error("Can't drop!",e)

CODE 6: DBMANAGER LAMBDA (THIRD PART)

The last part of dbmanager lambda executes a table dump into a csv file and if everything is done, it drops the respective table from database. AWS Lambda is also used to compute aggregate data, to give users a broader vision over time. The choice to aggregate data with lambda was made to reduce database query received from different customers: as in previous lambda, this function called aggregation, is executed every predefined period of time, invoked by a CloudWatch event.

Data aggregation is computed in four different granularity: five minutes, one hour, six hour and one day.

(26)

25 info("Lambda starting up")

try:

# gather db info from env varaiables

dbname = os.environ["DB_NAME"] user = os.environ["DB_USER"] passwd = os.environ["DB_PASS"] dbhost = os.environ["DB_HOST"]

metrics = os.environ["METRICS"].split(",") if len(metrics)<=0:

raise Exception("Bad metrics") except Exception as e:

fatal("Can't gather env variables:", e)

CODE 7: AGGREGATION LAMBDA INITIALIZATION

As usual, it starts with an initialization phase, getting environment variables and setting database connection.

delta_t = [5*60,60*60,6*60*60,24*60*60] delta_s = ["5m","1h","6h","1d"]

# this is called at lambda startup

def handler(event, context): db.cursor()

# generic object for aggregation of multiple tables

aggr = DB.Aggregate() now = timestamp() item_count=0

info("aggregate to",now)

to_aggr = aggr.get_unaggregated(now,delta_t[0]) info(to_aggr)

for a in to_aggr: aggr_spec =

aggr.get_aggregation_times(a["last_aggregated"].timestamp(),now,delta_t,delta_s) item_count+=aggr.aggregate(a,aggr_spec)

rtime = context.get_remaining_time_in_millis() if rtime<2000:

break

info("Inserted:",item_count) return item_count

(27)

26 The handler function, creates a generic aggregator object, retrieves unaggregated data from database and starts computing them. At the end of this process, the number of aggregation computed is returned.

Alarms detention is managed by alarm lambda function, when some monitored value comes out the pre-established interval, it creates new records in alarms table.

def handler(event, context): db.cursor()

# generic object for alarms

alrms = DB.Alarms()

# create objects for DB access

# retrieve needed checks

now = timestamp() item_count=0

info("check alarms up to",now)

inst_to_check = alrms.get_unchecked_installations(now,mindelta) info(inst_to_check)

for inst in inst_to_check:

item_count+=alrms.check(inst,now)

rtime = context.get_remaining_time_in_millis() if rtime<2000:

break

info("Inserted:",item_count) return item_count

CODE 9: ALARM LAMBDA HANDLER

The handler retrieves the installations not checked yet, then for each of them, it discover if some value is out of the interval and in case it sends notification to the user.

The process of devices provisioning on AWS IoT is done through lambda function. The provisioning Lambda, is also used to set the device’s certificate state.

(28)

27 The handler function is basically an entry point that checks the command received as a function parameter, invokes a corresponding external function to make the job. Commands received can be:

 PROVISION: starts device provisioning with or without CSR;  ACTIVATE: activate device certificate to allow it to work;  DISACTIVATE: deactivate device certificate;

def handler(event, context):

info("Gathering provision parameters",event) db.cursor()

cmd = event.get("cmd") try:

uid = event["uid"] except Exception as e: fatal("Bad parameters") if cmd=="PROVISION":

try:

csr = event.get("csr") except Exception as e: fatal("Bad parameters") if True:

# create new device

if csr: return provision_with_csr(uid,csr) else: return provision_with_key(uid) elif cmd=="ACTIVATE": certificate_set_status(uid,"ACTIVE") elif cmd=="DISACTIVATE": certificate_set_status(uid,"INACTIVE") else:

fatal("Unknown command")

(29)

28 Two ways are planned to register a thing on AWS IoT:

 providing a private CSR request to let AWS approve the certificate;

 getting the AWS certificate automatically generated. Here AWS generates a certificate and a couple of keys that are sent back to the device.

What provision_ device function do, is to create a thing on AWS, attach a previously created certificate to it and attach a policy to the certificate. In this phase if something goes wrong, all operations are undone as showed in the exception part.

def provision_with_key(uid): thingname = cid+"_"+uid iot = AWS.IoT()

# create certificate

crt = iot.create_keys_and_certificate(setAsActive=True) dev = provision_device(uid,thingname,crt,iot)

dev["certificatePem"]=crt["certificatePem"] dev["publicKey"]=crt["keyPair"]["PublicKey"] dev["privateKey"]=crt["keyPair"]["PrivateKey"] return dev

def provision_with_csr(uid,csr): thingname = cid+"_"+uid iot = AWS.IoT()

# create certificate

crt =

iot.create_certificate_from_csr(certificateSigningRequest=csr,setAsActive=True) dev = provision_device(uid,thingname,crt,iot)

dev["certificatePem"]=crt["certificatePem"] return dev

CODE 11: PROVISIONING WITH CSR

(30)

29

2.1.8 - AWS services interaction and access policies

Amazon provides different methods to ensure security access at different application layers. First of them is defined by Identity and Access Management (IAM) service, which helps securely control access to AWS resources: the access management portion of IAM helps the administrator define what a user or other entity is allowed to do in an account (authorization). Amazon defines access roles using permission policies and permission boundaries: they are JSON policy documents that, when attached to an identity or resource, defines their permissions. Permission def provision_device(uid,thingname,crt,iot):

c_arn = crt["certificateArn"] c_id = crt["certificateId"]

thing = iot.create_thing(thingName=thingname)

iot.attach_thing_principal(thingName=thingname,principal=c_arn)

iot.attach_principal_policy(policyName=cid+"_iot_policy",principal=c_arn) dh = DB.Device(uid)

dev ={

"thing":thingname,

"thing_arn":thing["thingArn"], "thing_id":thing["thingId"], "certificate_id":c_id,

"certificate_arn":c_arn }

try:

if not dh.update(dev):

raise Exception("Failed update") except Exception as e:

iot.detach_principal_policy(policyName=cid+"_iot_policy",principal=c_arn) iot.detach_thing_principal(thingName=thingname,principal=c_arn)

thing = iot.delete_thing(thingName=thingname)

iot.update_certificate(certificateId=c_id,newStatus="INACTIVE") iot.delete_certificate(certificateId=c_id,forceDelete=True) fatal("Rolled back due to DB error",e)

return dev

(31)

30 boundary is an advanced feature which use polices to limit the maximum access that a principal can have.

That control is not properly related to the functionality of the system described in this thesis, rather it regards definition of user access rights to AWS services. As an example, the usual division implemented in companies, where the access to the billing and development parts are assigned to different users through the definition of specific policies. The second authentication method for accesses is about X.509 certificates, which associate a public key with an identity contained in a certificate. AWS also support several certificate-signing algorithms, such as SHA512WITHRSA, RSASSAPSS, DSA_WITH_SHA256, ECDSA-WITH-SHA384 and many others.

As mentioned in the IoT chapter, all devices connected to the IoT endpoint must have an active certificate to authenticate, and each certificate must have attached a policy document to describe their permissions. Policies differ in their structure depending on what they refer to. Three types are used in this project:

 identity based policy: can be attached to a principal (or identity), such as an IAM user, role, or group, and control what actions that identity can perform, on which resources, and under what conditions.

 Resource-based policy: can be attached to a resource and allow to specify what actions a specified principal can perform on that resource and under what conditions.

 Access control policies: allow to control what principals can access a resource.

(32)

31 The previous code, shows the policy associated to all devices, it includes a version field and a list of statements that define the access rights. Each statement contains:

 Effect field: can be Allow or Deny;

 Action: is the action for which is granted or denied that permission;  Resource: the resource that has affected by the action.

Resources are identified through a unique Amazon Resource Name (ARN), which consists of the string “arn:aws:”, followed by the service { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action":["iot:Connect"], "Resource": ["*"] }, { "Effect": "Allow", "Action": ["iot:Publish"], "Resource": ["arn:aws:iot:{{region}}:{{account}}:topic/{{customer_id}}/${iot:Connection.Thing.T hingName}/sink", "arn:aws:iot:{{region}}:{{account}}:topic/{{customer_id}}/${iot:Connection.Thing.Th ingName}/adm_out"]}, { "Effect": "Allow", "Action": ["iot:Receive"], "Resource": ["arn:aws:iot:{{region}}:{{account}}:topic/{{customer_id}}/${iot:Connection.Thing.T hingName}/adm_in"]}, { "Effect": "Allow", "Action": ["iot:Subscribe"], "Resource": ["arn:aws:iot:{{region}}:{{account}}:topic/{{customer_id}}/${iot:Connection.Thing.T hingName}/adm_in"] }] }

(33)

32 name (iot), the region where the service resides, the account identifier and a string to indicate the resource in this path. ARNs here, are specifying MQTT topics on which a device can act; they are parametric so to be easy instantiate for different solutions.

(34)

33

2.1.9 - Cloud Architecture

The above picture shows the complete cloud architecture, pointing out the different access points and how data is conveyed through different

(35)

34 services, to build a robust and scalable system. As showed, there are two access points in the system, one reserved to users, the other for devices. Users access point is the web server, it is built in an AWS EC2 instance, then a public IP address is assigned to be reachable. Users make HTTP requests to web server, it query the database and use lambda function for device provisioning.

From the device point of view, registered data is sent to the AWS IoT endpoint and after a pre-processing, it reaches the SQS queue. Then the ingestion function empties the queue and stores data into the database. Database resides in a Postgresql 9.0 instance, built on AWS RDS

service. All the other operations the system provides, such as aggregated measures computation, alarms detection, sending automatic emails are computed by a Lambda function which are invoked by a CloudWhatch event at specified time interval.

2.2 - Web Server

The web server consists of two elements: Tornado server and Nginx proxy. They are both instantiated into a container and a private network is configured to let them talk; this structure is built into an AWS EC2 instance, reachable by public IP address assigned to the Nginix service. Tornado deals with managing HTTP requests, querying the database, and build answers; Nginx takes the role of proxy server, requests are received, managed and send to Tornado.

(36)

35

2.2.1 - Tornado framework

Tornado is a Python web framework and asynchronous networking library. By using non-blocking network I/O, Tornado can scale to tens of thousands of open connections, making it ideal for long polling, websocket and other applications that require a long-lived connection to each user.

The Tornado version used in this thesis is 5.0, to make the most of its asynchrony potential, Python 3.5 is used, which introduce the async-await syntax constructs to manage coroutines.

The general structure of a Tornado web application consists of an Application object in which the pairs (URIs, RequestHandler objects) defined, assign each request to the corresponding Python class that manages it. Within the RequestHandler class it is possible to define different functions corresponding to the types of the HTTP protocol request methods (GET, POST, PUT, ..).

An objective of this thesis is to create an almost generic backend server easy adaptable to specific solutions with small changes, so that it has an internal structure consisting essentially of three modules:

 handler module: groups the classes that manage the application APIs;

 tbus module: manages utility functions for server support;

 tmodels module: defines the database access classes that prepare and execute queries.

The pairs defined in the Application object along with the request methods, define the web server APIs, each of which is therefore

(37)

36 implemented through a RequestHandler class, that represent its business logic. However, each of these classes is actually inherited by the parent class tornado.web.RequestHandler defined in Tornado, which contains initialization and finalization methods for incoming requests.

For the generic web server, the following APIs are provided:

 user management: implements user login, logout, creation, profile, user details and list of user, update and reset password;

 device management: implements device creation, update, retrieve detail;

 management of device metrics: implements creation, update and retrieve detail of device metrics;

 machine management: implements machine creation, update, retrieve details and list of machine;

 management of machine metrics: implements creation, update and retrieve detail of machine metrics;

 management of aggregated metrics: implements creation, update and retrieve details of machine metrics;

 management of tenant and sites: implements creation, update, retrieve detail of tenant and sites;

 alarm management: implements alarm retrieve;

 report generation: implements report download and list of reports;

 management of commands: implements sending functions to device;

(38)

37

 data management: implements requests to retrieve data produced by devices.

All of this RequestHandler inherits from BaseHandler class, which manage common functionality such as initialize and finalize incoming requests, generate and verify session token and implements python decorators for security access controls.

(39)

38 User authentication is managed with sessions and bearer authorization token, generated with JWT (JSON WEB TOKEN) open standard. JWT token structure consists of three parts separated by dots, which are:

Header: includes token type and the hashing algorithm being used

(HMAC SHA256 or RSA);

Payload: consists of claims which are statements about an entry

and additional data;

Signature: it is generated taking the encoded header, the encoded

payload, a secret, the algorithm specified in the header, and sign that.

async def generate_session_token(self,user={},exp=30,logintype=None): try:

data = {}

now = int(time.time()) dnow = utctimestamp() dend = utcadd(dnow,exp)

data["exp"] = now +60*60*24*exp data["iss"] = "toi"

data["iat"] = now

data["jti"] = gen_uuid() data["uid"] = user["uid"] data["ltp"]=logintype

token = jwt.encode(data, user["token_key"], algorithm='HS256') self.token_expires = data["exp"]

self.rawtoken = token

await self.session.set(data["jti"],{ 'token':token,

"user_uid": user["uid"], 'expired':dend,

"ip":self.user_ip, "create_date":dnow })

except Exception as e:

self.log_exception('Exception in generating token: ',e) return token

(40)

39

The code below shows how sessions are created; they consists of a JWT token and additional data, such as expired timestamp, user unique identifier and user IP address and it is stored in the database.

async def get(self):

self.log_info("Login user")

if "Authorization" in self.request.headers and self.request.headers["Authorization"].startswith("Basic "): dgs = self.request.headers["Authorization"][6:] dgs = base64.b64decode(dgs).decode("utf-8") usr,pwd = dgs.split(":",1)

setcookie = self.get_argument("setcookie",False) if not chk_email.match(usr):

self.log_error("type error: bad username")

self.write_rest(403,status="error",msg="Bad email") uu = await QTUser.login({'email':usr,'password':pwd}) if not uu:

self.log_error("type error: bad username or password")

self.write_rest(403,status="error",msg="Bad username or password") return

if setcookie:

cookie = self.get_secure_cookie("WIREF_LOGIN") if cookie:

session = await self.cache.get_by_uid(cookie.decode("utf-8")) if not session:

token = await self.generate_session_token(uu) session = await self.cache.get({'token':token}) self.set_secure_cookie("WIREF_LOGIN",session["uid"]) else:

token = session["uid"] self.rawtoken=token

self.token_expires = session["exp"] else:

token = await self.generate_session_token(uu) session = await self.cache.get({'token':token})

self.set_secure_cookie("WIREF_LOGIN",session["uid"]) else:

token = await self.generate_session_token(uu)

self.session = await self.cache.get({'token':token}) self.log_info("generating token", self.session)

(41)

40

At login time, the backend verify the secret credential and looks for coockie: if there is, it retrieves user identity from it, if not, a new session is created; in any case, the respective token is sent back to the applicant. From this point over, each request must keep the bearer token in the header.

The backend also provides functionality to manage different type of users, which have different access right, the following are planned:

superadmin: has access privileges almost everywhere;

 admin: he can be an administrator of a part of the industry, so he has complete access to his domain;

 installer: has access rights to devices and machine installed by him;  reader: has only rights to read data from one or more devices. The security access mechanism is implemented by Python decorators which in the context of design pattern, dynamically alter the functionality of a function, method or class without having to directly use subclasses. Decorators are defined in the BaseHandler of the web server, they cover all type of users:

tauth: check if the user is authenticated;

self.set_secure_cookie("WIREF_LOGIN",self.session["uid"]) data = {'token':token}

self.log_info("User ", uu['uid'], " logged in") self.write_rest(200,data=data)

(42)

41

tcustomauth: is a parametric decorator that, given a list of access

types, checks whether the logged user belongs to one of those classes

tadmin: check if the logged user is an administrator;

tmachine: check if the logged user has access to the specified

machine;

tdevice: check if the logged user has access to the specified device;

tsuperadmin: check if the user is a super administrator.

def tcustomauth(roles): def _auth_(method):

@functools.wraps(method)

async def wrapper(self,*args,**kwargs): try:

self.log_info("Custom auth ", roles)

usr_roles = [r for (t,r,s) in self.access_info] res = set(roles) & set(usr_roles)

if not res:

self.log_error("User ",self.tuser," unauthorized ") self.write_rest(403,status="error",msg="Unauthorized") return

except Exception as e:

self.log_error("Bad authorization header",e) self.write_error(404,"No such user")

return

return (await method(self,*args,**kwargs)) return wrapper

return _auth_

CODE 16: CUSTOM AUTHENTICATION DECORATOR

Every request method into the handlers, is now appropriately decorated, and the APIs code is more readable and easy to maintain.

(43)

42

The tbus module contains specific classes and functions to support handlers. It is divided into three files that deal with:

 email management: functions designed to compile and send automatic e-mails;

 management of log files: is a class implementing methods to log information coming from the system, it uses the Python structlog library;

 utility: implements functions for generating unique identifiers, temporary passwords, timestamps in different formats;

 awsutility: contains function to invoke Lambdas on AWS, it uses

boto3 python library to interact with cloud.

The tmodels module implements as many classes as there are models of the database to be managed. It consists of a base class called ToiModels, which implements parametric functions for the most frequently used queries: insert, select, delete, update.

(44)

43 def insert_query(table='', data={}):

s = "INSERT INTO "+table+" ("+', '.join(['{}'.format(k) for k,_ in data.items()])+")"+" VALUES (" \

+', '.join(['%({})s'.format(k) for k,_ in data.items()])+")" return s

def select_query(table='', select_fields=[], where_field=None): if not select_fields:

s = "SELECT * " else:

s = "SELECT "+','.join(['{}'.format(x) for x in select_fields])+' ' s +="FROM "+table+" "

if where_field:

s +=" WHERE "+' AND '.join(["{}".format(k)+"=%({})s".format(k) for k,_ in where_field.items()])

if where_distinct and not where_field:

s += " WHERE "+' AND '.join(["{}".format(k)+"!=%({})s".format(k) for k,_ in where_distinct.items()])

return s

CODE 17: INSERT AND SELECT QUERY FUNCTIONS

These functions create the query string with placeholders for data entry.

ToiModels also implements function to retrieve query results as a

dictionary or a list of dictionaries, depending on single or multiple result records. Every model class inherits the functionality of ToiModels. Models defined in this project are:

qtuser: manages queries on user table;

qtdevice: manages queries on device table;

qtmachine: manages queries on machine table;

qttenant: manages queries on tenant table;

qtsite: manages queries on site table;

(45)

44

qtalarm: manages queries on alarm table;

qtaccessinfo: manages queries on accessinfo table;

qtsession: manages queries on session table;

qtdevicemetric: manages queries on devicemetric table;

qtmachinemetric: manages queries on machinemetric table;

qtaggregatemetric: manages queries on aggregatemetric table;

qtdata: manages queries on data table;

qtcommand: manages queries on command table.

FIGURE 6: WEB SERVER MODELS CLASS HIERARCHY

The structure of each model includes a class representing the table model, and class methods, which specify the kind of query. What each method do is to call the appropriate function to create a query string, execute and return the formatted result to the caller. Special methods such as login requests or creation requests, execute additional checks to improve

(46)

45

security, but in general, checks are usually made by handlers. psycopg2 is the Postgresql adapter for Python to interact with databases and it is the one used in this web server. Unfortunately that library is not asyncronus so, to ensure complete asyncronus system, the wrapper library momoko is used in query execution. It implements functions to set up a pool of connections and execute single and multiple query in asyncronus way.

class QTDevice:

async def create(data): try:

dev_data = {

'uid':gen_uuid(),

'on_chip_id':data['on_chip_id'], 'vm_uid':data.get('vm_uid',''), "vm_slot":data.get('vm_slot',''), "bc_slot":data.get('bc_slot',''), "name":data.get('name',''),

"type":data.get('type',''),

"geolocation": data.get('geolocation',''),

"publish_period": data.get('publish_period',''), "machine":data.get('machine',''),

"tenant":data.get('tenant',''), "site":data.get('site',''), "online":data.get('online',''), 'create_date':utctimestamp() }

q = QToiModels.insert_query(table=QTDevice.table, data=dev_data) q += " ON CONFLICT (on_chip_id,inst_uid) DO NOTHING"

res = await db().execute(q, dev_data) if not res.rowcount:

return False except Exception as e: print(e)

return None

return dev_data['uid']

(47)

46

User password are coded in the user model before being inserted into the database; the bcrypt Python library is used, which implements a version of Bruce Schneier's Blowfish block cipher with modifications designed.

@asyncio.coroutine def hashpwd(pwd):

p = yield executor().submit(bcrypt.hashpw, bytes(pwd,"utf-8"), bcrypt.gensalt(13))

return str(p, 'utf-8') @asyncio.coroutine

def check_password(hspwd,password):

hashed = yield executor().submit( bcrypt.hashpw, bytes(password,"utf-8"), bytes(hspwd,"utf-8"))

return hashed

CODE 19: PASSWORD HASHING AND CHECK

2.2.2 - Nginx

Nginx is a web server which can also be used as a reverse proxy, load balancer, mail proxy and HTTP cache.

(48)

47

The role of Nginx in this project is a proxy server: each incoming request arrive to Nginix server ,which rewrite the URI and send it to Tornado. server {

listen 80;

server_name localhost; root /var/www/html; location /api/ {

rewrite /api/(.+) /$1 break; proxy_pass_header Server;

proxy_set_header Host $http_host; proxy_redirect off;

proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_pass http://backend;

}

location /auth {

proxy_pass_request_body off; proxy_set_header Content-Length "";

proxy_set_header X-Original-URI $request_uri; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://localhost/api/auth; } location / { return 404; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } }

CODE 20: NGINX CONFIGURATION FILE

All rules Nginx uses are specified into its configuration file, it accepts requests on a URI that starts with /api/ and directs them to the backend by rewriting the URI so as to create a masking level.

The reason for the presence of proxy server is due to the greater security of access to the Tornado server, thanks to the URI masking performed at

(49)

48

the arrival of each request, as well as the greater scalability of the system thanks to the Nginx upstream function.

In presence of many requests, the server's performance could get worse; to avoid this, it is possible to create several independent instances of Tornado server and set upstream directive in the Nginx configuration file to distribute incoming requests between different backends.

http { upstream frontends { server toibackend_1:7777; server toibackend_2:9999; … } Server{ … } }

CODE 21:NGINX UPSTREAM CONFIGURATION

2.2.3 - Docker

Docker is an open-source project that automates the deployment of applications to internal software container, providing additional abstraction through Linux operating system virtualization. Docker uses the isolation capabilities of Linux kernel resources such as cgroups and namespaces to allow independent "containers" to coexist on the same Linux instance, avoiding the installation and maintenance of a virtual machine. The Linux kernel namespaces mostly isolate what the application can see of the operating environment, including the process tree, network, user IDs and mounted file systems, while cgroups provide isolation resources, including CPU, memory, block I/O devices and network. An image is an executable package that includes everything needed to run an application: the code, a runtime, libraries, environment

(50)

49

variables, and configuration files. A container is a runtime instance of an image, what the image becomes in memory when executed. Docker also provides default images that show all top level images, their repository and tags, and their size.

In this project Docker is used to easy build up the server part, namely two containers are set up for Nginx and Tornado through predefined images of Python 3.5 and Nginx.

FROM python:3.5-jessie COPY requirements.txt .

RUN pip install -r requirements.txt

CMD ["/app/app.sh"]

CODE 22:PYTHON DOCKER IMAGE

Inside the docker file, is specified the image to build, the entry point of the application and other additional software; the entry point is a shell script to start the application and it is executed as soon as the container is built and run. Additional software is provided in the Docker file to run the application:

 Nginx: logrotate is installed to rotate logs. As log files grow, it becomes necessary to manage the logging mechanisms to avoid filling up disk space. Log rotation is the process of switching out log files and possibly archiving old files for a set amount of time. Also fcgiwrap is needed, that is a simple server for running CGI applications over FastCGI;

(51)

50

 Python3.5: through PIP tool, all necessary frameworks and libraries are installed. Requirements are:

◦ Tornado 5.0; ◦ Momoko 2.2.4;

◦ Structlog 18.1: it makes logging in Python less painful and more powerful by adding structure to log entries;

◦ psycopg2-binary 2.7.5;

◦ pycrypto 2.6.1: is a collection of both secure hash functions (such as SHA256 and RIPEMD160), and various encryption algorithms (AES, DES, RSA, ElGamal, etc.);

◦ python-jose 3.0.0: a JavaScript Object Signing and Encryption (JOSE) implementation for Python which includes JWT APIs; ◦ bcrypt 3.1.4: is a password hashing function based on Blowfish

cipher;

◦ boto3: is the Amazon Web Services (AWS) SDK for Python, which allows to write software that makes use of Amazon services.

Once containers are created and built, they need to communicate through a network. For this purpose, an other tool called Docker Compose is used.

Compose is used for multi-container Docker applications, it provides a

YAML file to declare services and other details: for each service, is specified the Docker source file, opened ports to the application, volumes mounted, environment variables and links to other services. In this case, only the Nginx service has a link to Python service to send incoming request, Docker Compose automatically set up a network between them.

(52)

51 version: "3.1" services: toibackend: build: ./docker/python hostname: toibackend volumes: #- ./tstack:/app - ${BACKEND_SOURCES}/sources:/sources - ${BACKEND_STORAGE}/toicontents:/tcontents - ${BACKEND_STORAGE}/repos:/repos - ${BACKEND_STORAGE}/packages:/packages environment: - TRUN=toibackend - TMOD=${TMOD} - DOCKER_USER=tuser - DOCKER_GROUP=tuser - HOST_USER_ID=${TUSER_UID} - HOST_GROUP_ID=${TUSER_UID} - TOI_TESTMODE=${TOI_TESTMODE} ports: - "7777:7777" http: build: ./docker/nginx hostname: nginx ports: - "80:80" - "443:443" volumes: - /var/www/html/img - ${BACKEND_STORAGE}/toicontents/docs:/var/www/html/docs - ${BACKEND_STORAGE}/packages:/var/www/html/packages - ${BACKEND_STORAGE}/tcontents/installer:/var/www/html/installer - ${NGINX_CONF}/logs:/var/log/nginx - ${NGINX_CONF}/${NGINX_ETC}/default_nginx.conf:/etc/nginx/default_nginx.conf - ${NGINX_CONF}/${NGINX_ETC}/nginx.conf:/etc/nginx/nginx.conf - ${NGINX_CONF}/${NGINX_ETC}/sites-available:/etc/nginx/sites-enabled - ${BACKEND_STORAGE}/repos:/repos restart: unless-stopped links: - toibackend

(53)

52

This tool allows to get several benefits from Docker, such as masking the network, while abstracting the complexity of the stack and the Docker files themselves.

This web server is finally built into an AWS EC2 instance and a public IP address is assigned to it, then a further encapsulation is implemented for Tornado server, thanks to AWS, Docker and Nginx.

2.3 - Database Postgresql

PostgreSQL is a powerful open source relational database system that uses and extends the SQL language, that securely store and scale the most complex data workloads. It comes with many features designed to help developers build applications and manage data, regardless of size. In addition to being free and open source, PostgreSQL is highly extensible by defining data types and custom functions.

(54)

53

Postgresql is used as a database manager, the generic database contains the following tables:

user: contains informations abous users and a unique identifier;

accessinfo: this table relates users and their access permissions to

tenant-site cuples;

device: contains devices information, with machine references;

device_metric: metrics description with devie reference;

machines: machines anagrafics with tenant-site reference;

machine_metric: metrics with machine reference;

aggregate_metric: table of aggregated metrics associated to

tenant-site couple;

data: table of data sent by the devices;

tenant: table of tenants details;

site: site description;

command: table of commands sent to the devices;

 sessions: store session tokens and user identifier;  alarm: alarm table with machine reference;  report: report table with machine reference.

(55)

54

(56)

55

Data table stores data coming from all devices, each of which might send messages every second. Machines could be equipped with more than one device and a tenant-site couple consists of multiple machines. In this scenario, table data grows fast and query performance may get worse. To avoid this problem, the inheritance of Postgresql tables is introduced: at daily intervals, a new table is created and renamed with the date of the day; a trigger function is created to insert incoming messages into the right data table. This reduces the size of tables and indexes, improving query performance.

def set_time_series(cur):

t_name = "day_"+str(datetime.datetime.now().isoformat()) q ="CREATE TABLE \""+t_name+"\" ( ) INHERITS (data)" cur.execute(q)

q = "CREATE OR REPLACE FUNCTION data_insert_trigger() \

RETURNS TRIGGER AS $$ \

BEGIN \

INSERT INTO \""+t_name+"\" VALUES (NEW.*); \

RETURN NULL; \

END; \

$$ \

LANGUAGE plpgsql;" cur.execute(q)

q = "CREATE TRIGGER insert_data_trigger \

BEFORE INSERT ON data \

FOR EACH ROW EXECUTE PROCEDURE data_insert_trigger();" cur.execute(q)

CODE 24:INHERITED TABLE AND TRIGGER FUNCTION CREATION

The process of creating daily tables is automated by an AWS Lambda function called by a CloudWatch event each day at midnight.

(57)

56

2.4 – Design and development of a generic industrial IoT

firmware for the 4ZeroBox device

Firmware design is based on those already developed by TOI srl, the intention is to develop an almost generic firmware as adaptable as possible to various company requirements, taking into account the computation limits and memory capacity of the microcontrollers used.

Old firmware are substantially procedural and not generic, this has involved a difficult maintenance and mostly, for each project developed, the design of an ad hoc firmware starting from scratch, not exploiting code reusability.

2.4.1 - 4ZeroBox

(58)

57

4ZeroBox is the generic firmware target architecture, produced by TOI srl. It is an easy to configure and easy to program modular hardware electronic unit: it is perfectly suited for data acquisition and processing from existing systems and is fully compatible with hundreds of standard sensors. 4ZeroBox allows:

 IoT enabling an existing machine to have a distributed sensors network into the plant operations and acquire valuable information, thus bypassing an obsolete PLC;

 Seamless Integration with enterprise software infrastructures further extending the value of a ready to deploy toolkit.

Hardware specification:

 DIN-rail mountable (9 slots);  5V Supply voltage;

 Connectivity: WiFi (Station and AP mode supported); Bluetooth Low Energy; Ethernet (Based on Microchip LAN8710A transceiver); RS-485 and RS-232; CAN (based on Microchip MCP2515T controller integrated with transceiver);

 4 analog input channels configurable as: 20mA single-ended; 4-20mA differential; 0-10V;

 3 non-invasive current sensor channels;

 4 analog channels configurable for RTD or contact/proximity sensors;

(59)

58

 2 opto-isolated digital inputs with configurable input voltage (24V to 5V);

 2 sink digital output (60A @ 30V);  1 Digital I/O + 2 Digital Input (3.3V);  2 NO/NC Relay (10A @ 250V AC);  2 on-board mikroBUS sockets;  MicroSD card slot;

 LiPo battery support with on board charging unit;  JTAG support;

 RGB status led;  Power led;

 ESP32 32bit Microcontroller (240MHz clock, 4Mb of Flash, 312Kb SRAM).

4ZeroBox is able to acquire data in different ways:

 Data Gathering: Acquire digital data from RS232, RS485, Ethernet, CAN and other digital ports of the PLC. On-board filtering of data and extraction of Key Performance Indicators optimize the network bandwidth and cloud resources keeping the processing at the edge node devices.

 Retrofitting: Acquire data in parallel to the PLC using the available sensors or installing new probes. A solution tailored for data acquisition from old machines where PLCs are obsolete or where application code and specifications are not accessible.

Riferimenti

Documenti correlati

In the gure 5.2 are displayed the agreement between the experimental x-ray brightness (the black crosses) and the simulated ones (red lines) at dierent time steps, the latter

As the sample of dense planets with well-constrained masses and radii continues to grow, we will be able to test whether the fixed compositional model found for the seven dense

In general, REST-based approach in Wireless Sensor Networks (WSNs) treats sensors as they were Internet resources accessible through a Unique Resource Identifier and the

– Cluster Compute Quadruple Extra Large Instance: 23 GB di memoria, 33.5 Compute Units EC2 (2 Intel Xeon X5570, architettura quad-core “Nehalem”), 1690 GB di spazio di

Plusieurs de ces consignes se trouvent dans le De reg.. Il convient en outre que le gouverneur se garde d’introduire des nouvelles coutumes, et il doit respecter les

In the experiments presented in this paper, the side weirs can be considered ‘short’ as the longest is 1.15 times the main channel width; however, the three-dimensional bed

Using the OCCI ontology we define two kinds that are associated with the basic components of a monitoring infrastructure: the collector link, that performs measurements, and the

In order to provide evidence of the benefits offered by this service model, a weather monitoring service is developed using Node.js, which is based on the devised concept and