PyScada on Raspberry PI for temperature monitoring with DS18B20 on 1-Wire – Part 1 – Software Installation

When looking for a temperature monitoring solution I considered a number of options but landed on the DS18B20 sensors in a TO-92 package (Datasheet Link). These nifty little sensors are cost effective and provide an accuracy of +-0.5 degrees over a range much wider than the temperature range in my house. These also provide a 1-wire interface that is compatible with the old Raspberry PI model B I have in the cupboard.

Initial operating system configuration

Starting with the RaspberryPI model B I went for the Rasbian Stretch lite iso (Download Link) and wrote it to an SD card using Etcher (Download Link). Connecting the RaspberryPI to a HDMI cable, usb keyboard and the freshly written SD card the system was ready for first boot.

After first power up the login with the default username and password

pi
raspberry

After login run the update commands to ensure that our operating system is up to date

sudo apt-get update
sudo apt-get dist-upgrade

Then perform some initial configuration using the raspi-config

 sudo raspi-config 

Raspi-01

From this application perform the following configurations

Set the password to something unique instead of the default

Menu 1 - Change Password

Set the Localisation settings

Menu 4 - Localisation
Menu I1 - Change Locale
Set to en_AU UTF-8 UTF-8
Untick en_GB UTF-8
Set en_AU UTF-8 to default

Set the timezone

Menu 4 - Localisation
Menu I1 - Chage Timezone

Enable SSH so we can perform the remainder of the configuration from a remote PC

Menu 5 - Interfacing Option
Menu P2 - Enable SSH

Enable the 1-wire support

Menu 5 - Interfacing Option
Menu P7 - Enable 1-wire

Select finish to complete the configuration
Reboot
On reboot note the “My IP Address is 192.168.1.14” line on the boot screen, we will need this to remotely login to the raspberry pi

Remotely Connect the Raspberry PI

To connect to the Raspberry PI remotely we will use the SSH server we enabled in the previous section. My preferred SSH client for Windows is putty (Download Link)

Run putty and all we need to set is the IP Address of the Raspberry PI and click open. This will provide a remote command prompt to complete the installation of PyScada and the testing of our 1-wire network.

Installation and configuration of PyScada

These instructions are based on the instructions at http://pyscada.rtfd.io/ however these instructions cover a wide range of linux distributions and hardware and I struggled to get the correct combination for the Raspberry PI.

Create a user dedicated to the PyScada application

sudo -i
sudo useradd -r pyscada
sudo mkdir -p /var/www/pyscada/http
sudo chown -R pyscada:pyscada /var/www/pyscada
sudo mkdir -p /home/pyscada
sudo chown -R pyscada:pyscada /home/pyscada
sudo ln -s /var/www/pyscada/ ~/www_pyscada

Install the dependencies, PyScada and then create the django project

sudo apt-get -y install python-pip libhdf5-dev python-dev nginx gunicorn
sudo pip install cython
sudo pip install numpy
sudo export HDF5_DIR=/usr/lib/arm-linux-gnueabihf/hdf5/serial/
sudo pip install h5py
sudo pip install https://github.com/trombastic/PyScada/archive/dev/0.7.x.zip
cd /var/www/pyscada/
sudo -u pyscada django-admin startproject PyScadaServer

Edit the configuration files

sudo nano /var/www/pyscada/PyScadaServer/PyScadaServer/urls.py

Set the file to the following:

"""PyScadaServer URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include('pyscada.hmi.urls')),
]
sudo nano /var/www/pyscada/PyScadaServer/PyScadaServer/settings.py

Edit the file to the following:

Add this to the top

#!/usr/bin/python
# -*- coding: utf-8 -*-

Change

DEBUG = False

Set

ALLOWED_HOSTS = ['*']

Set

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'pyscada',
    'pyscada.modbus',
    'pyscada.phant',
    'pyscada.visa',
    'pyscada.hmi',
    'pyscada.systemstat',
    'pyscada.export',
    'pyscada.onewire'
]

Add this to the bottom

STATIC_ROOT = '/var/www/pyscada/http/static/'

MEDIA_URL = '/media/'

MEDIA_ROOT = '/var/www/pyscada/http/media/'

# PyScada settings
# https://github.com/trombastic/PyScada

# email settings
DEFAULT_FROM_EMAIL = 'example@host.com'
EMAIL_HOST = 'mail.host.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'pyscada@host.com'
EMAIL_USE_TLS = True
EMAIL_USE_SSL = False
EMAIL_HOST_PASSWORD = 'password'
EMAIL_PREFIX = 'PREFIX' # Mail subject will be "PREFIX subjecttext"

# meta informations about the plant site
PYSCADA_META = {
        'name':'A SHORT NAME',
        'description':'A SHORT DESCRIPTION',
}

# export properties
#
PYSCADA_EXPORT = {
        'file_prefix':'PREFIX_',
        'output_folder':'~/measurement_data_dumps',
}

The file at the end should look something like mine below (note the secret key will be different)

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
Django settings for PyScadaServer project.

Generated by 'django-admin startproject' using Django 1.11.5.

For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '8*5gy8$$e8&+cka+&a1lz!#_)s*#zooz6d!+7!f*j%z+uxx376'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False

ALLOWED_HOSTS = ['*']

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'pyscada',
    'pyscada.modbus',
    'pyscada.phant',
    'pyscada.visa',
    'pyscada.hmi',
    'pyscada.systemstat',
    'pyscada.export',
    'pyscada.onewire'
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'PyScadaServer.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'PyScadaServer.wsgi.application'

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'

STATIC_ROOT = '/var/www/pyscada/http/static/'

MEDIA_URL = '/media/'

MEDIA_ROOT = '/var/www/pyscada/http/media/'

# PyScada settings
# https://github.com/trombastic/PyScada

# email settings
DEFAULT_FROM_EMAIL = 'example@host.com'
EMAIL_HOST = 'mail.host.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'pyscada@host.com'
EMAIL_USE_TLS = True
EMAIL_USE_SSL = False
EMAIL_HOST_PASSWORD = 'password'
EMAIL_PREFIX = 'PREFIX' # Mail subject will be "PREFIX subjecttext"

# meta informations about the plant site
PYSCADA_META = {
        'name':'A SHORT NAME',
        'description':'A SHORT DESCRIPTION',
}

# export properties
#
PYSCADA_EXPORT = {
        'file_prefix':'PREFIX_',
        'output_folder':'~/measurement_data_dumps',
}

Configure the PyScada Installation

Build the basic instance of PyScada

cd /var/www/pyscada/PyScadaServer
sudo -u pyscada python manage.py migrate
sudo -u pyscada python manage.py collectstatic
sudo -u pyscada python manage.py loaddata color
sudo -u pyscada python manage.py loaddata units

Create the admin user within PyScada

sudo -u pyscada python manage.py createsuperuser

Note your username and password you will need this later to login

Configure nginx

Get the nginx configuration from the PyScada source

sudo wget https://raw.githubusercontent.com/trombastic/PyScada/dev/0.7.x/extras/nginx_sample.conf -O /etc/nginx/sites-available/pyscada.conf
sudo nano /etc/nginx/sites-available/pyscada.conf

My version is below, the only item I set is the server_name to the IP address of my Raspberry PI.

# pyscada.conf

# the upstream component nginx needs to connect to
upstream app_server {
        server unix:/tmp/gunicorn.sock fail_timeout=0; # for a file socket
        #server 127.0.0.1:8000 fail_timeout=0; # for a file socket
}

# configuration of the server
server {

        listen 80 default;     # the port your site will be served on
        server_name 192.168.1.14;      # substitute your machine's IP address or                                                                                                                                                              FQDN
        charset utf-8;
        keepalive_timeout 5;
        client_max_body_size 75M;   # max upload size, adjust to taste

        # Django media
        location /media  {
                alias /var/www/pyscada/http/media;  # your Django project's medi                                                                                                                                                             a files - amend as required
        }

        location /static {
                alias /var/www/pyscada/http/static; # your Django project's stat                                                                                                                                                             ic files - amend as required
        }
        location / {
            # checks for static file, if not found proxy to app
            try_files $uri @proxy_to_app;
        }

        location @proxy_to_app {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect off;

            proxy_pass   http://app_server;
        }
}

Activate the PyScada nginx site, remove the default one, start the nginx service on boot and restart the service.

sudo ln -s /etc/nginx/sites-available/pyscada.conf /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo systemctl enable nginx.service
sudo systemctl restart nginx

Download the other systemd services from PyScada and activate them.


sudo wget https://raw.githubusercontent.com/trombastic/PyScada/dev/0.7.x/extras/service/systemd/pyscada_daq.service -O /lib/systemd/system/pyscada_daq.service
sudo wget https://raw.githubusercontent.com/trombastic/PyScada/dev/0.7.x/extras/service/systemd/pyscada_event.service -O /lib/systemd/system/pyscada_event.service
sudo wget https://raw.githubusercontent.com/trombastic/PyScada/dev/0.7.x/extras/service/systemd/pyscada_mail.service -O /lib/systemd/system/pyscada_mail.service
sudo wget https://raw.githubusercontent.com/trombastic/PyScada/dev/0.7.x/extras/service/systemd/pyscada_export.service -O /lib/systemd/system/pyscada_export.service
sudo wget https://raw.githubusercontent.com/trombastic/PyScada/dev/0.7.x/extras/service/systemd/gunicorn.socket -O /lib/systemd/system/gunicorn.socket
sudo wget https://raw.githubusercontent.com/trombastic/PyScada/dev/0.7.x/extras/service/systemd/gunicorn.service -O /lib/systemd/system/gunicorn.service
# enable the services
sudo systemctl enable gunicorn
sudo systemctl enable pyscada_daq
sudo systemctl enable pyscada_event
sudo systemctl enable pyscada_mail
sudo systemctl enable pyscada_export

I had issues with the service files provided so in each of them I needed to make the following change.

In each of these files

/lib/systemd/system/pyscada_daq.service
/lib/systemd/system/pyscada_event.service
/lib/systemd/system/pyscada_mail.service
/lib/systemd/system/pyscada_export.service
/lib/systemd/system/gunicorn.service

Use the following commands

sudo nano /lib/systemd/system/pyscada_daq.service
sudo nano /lib/systemd/system/pyscada_event.service
sudo nano /lib/systemd/system/pyscada_mail.service
sudo nano /lib/systemd/system/pyscada_export.service
sudo nano /lib/systemd/system/gunicorn.service

Replace the line

replace all the %u with pyscada or the username you intend to use

Then I needed to reduce the number or guincorn workers as the load was too high for my little Raspberry PI.

sudo nano /lib/systemd/system/gunicorn.service

Edit the line

ExecStart=/usr/bin/gunicorn --pid /tmp/gunicorn.pid --workers 8 PyScadaServer.wsgi:application

To

ExecStart=/usr/bin/gunicorn --pid /tmp/gunicorn.pid --workers 3 PyScadaServer.wsgi:application

From here restart the Raspberry PI and give it a few minutes to catch up and that is the end of the initial configuration. From a web browser we can now connect to the IP Address of the Raspberry PI and access the web based configuration interface.

Raspi-03

In the next post we will look at connecting and testing the 1-wire network to the Raspberry PI and after that the setup of PyScada. Click here (Link) for part 2 of this series.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s