Skip to content

Framework to expose IOT devices trough REST API and prometheus metrics

License

Notifications You must be signed in to change notification settings

panManfredini/IOTpy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

49 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

IOTpy

Framework to expose IOT devices trough REST API and Prometheus metrics. Perfect for Raspberry Pi.

  • You write your script to comunicate with the device
  • Define the variables that you want to expose
  • And IOTpy publishes those variables via REST API and Prometheus metrics

Installation

git clone https://github.com/panManfredini/IOTpy
cd IOTpy
pip install .

Usage

iotpy --dir <absolute-path-to-dir> --port <port-number>

# OR with env variable like below:
export IOTPY_DEVICES_DIR=<absolute-path-to-dir>
export IOTPY_DEVICES_PORT=<port-number>

With dir is intended the directory where your device files are stored (see below for more info).

Run the Example

In the Example folder, there is a simple device you can start with. This creates a device that exposes two variables test0 and test1, which are populated with randomly generated variable values.

# After installation and in the cloned folder
cd example
export IOTPY_DEVICES_DIR=$(pwd)
iotpy

Now visit http://localhost:8085.

How does it work

IOTpy is a webserver that loads dynamically the devices you place in a predefined directory, it extracts all the variables defined in those devices files and exposes them trough an HTTP API and Prometheus metrics.

What is a Device? For device is intended a class that inherits from the abstrac class iotpy.Device.Device. After you inherit the class, you must implement four methods:

  • init where you initialize your device (for example open a serial connection) and define the variables,
  • loop is a function that is automatically called every n seconds (where n is configurable, default is 2) where you can poll your device and update the variables value.
  • In the write method you execute an HTTP write request (somebody, trough the API has asked to write a value to the device), the method is called only if the device has defined that variable (so no need to double check), here you ask your device to set that variable then return True if success and False otherwise, if your device is read-only the just return always False.
  • Finally the cleanup method is used to gracefully shutdown the system, here for example, you close the serial connection with your device.

How does the IOTpy know about variables and when they change? The device class has methods implemented to interact with IOTpy server's variables, these are addVariable, setVariableValue and readVariableValue.

Minimal example: you find a little more complete example here.

from iotpy.Device import Device, addDevice

class myDevice(Device):
    
    def __init__(self,name):
        # You need to call constructor of Device
        Device.__init__(self,name)
        
        # here initialize your device connection...

        # adding a variables to the system
        self.addVariable("test0", "test variable")
        self.addVariable("test1")

        # call loop every 2 sec
        self.poll_loop_ms = 2000


    def loop(self):
        # here poll your device

        # and save variables values
        self.setVariableValue("test0", Value0)
        self.setVariableValue("test1", Value1)

        # if variable fails
        # self.setStatus(2, "TCP-REQUEST-FAIL")

    def write(self, name, val):
        # here execute write request on your device
        
        # and set variable value
        self.setVariableValue(name, val)

        return True  # False for failure

    def cleanup(self):
        # do some cleanup, for example close connection with device
        pass



#IMPORTANT: You must create and add the device to the list
addDevice( myDevice("test") )

Run the system: Now you just need to place all your devices files in a directory and run the IOTpy server with the absolute path to your dir.

iotpy --dir <path-to-your-dir>

An now you can visit http://localhost:8085 and check from the dev panel if your device is working correctly.

The HTTP API URLs

The server has a few defined URL routes:

Route HTTP Method Notes
/ GET returns a simple control panel.
/variables GET returns a JSON object with all defined variables and their current values, in the format reported below.
/metrics GET return the Prometheus metrics of your variable, you need to point Prometheus to this URL.
/write POST this route is used to request a variable value change, JSON payload is required in the format {"name":"varName","value":varValue}.
/restart GET this shutdow gracefully the server, Note: only if you defined the iotpy to run as a daemon then it will be restarted automatically.

Variable readout format:

// list of object 
[
    {
        "name": "name_str", 
        "value": Number, 
        "description": "description_str", 
        "lastUpdate_ms": 1612551768854, // time from linux epoch
        "status": 1,  // 0 - not yet read; 1 - Good;  > 1 - Error
        "error": "error_message or empty", 
    },
    {
        ...
    }
]

Enviroment Variables

Env Notes
IOTPY_DEVICES_DIR directory where devices are stored
IOTPY_DEVICES_PORT port number for the server
IOTPY_PROXY_PREFIX prefix to attach to all routes in case running behind a proxy

Docker

# build example 
docker build -f Docker -t <tag_name> .

# run example
docker run --rm --network host -e IOTPY_DEVICES_DIR=/iot/Devices -v <devices_path>:/iot openscada/iotpy:v0.3.1

Run IOTpy as a service (on linux)

These instruction only work on OS which uses systemd (so ubuntu for example). First you need to edit the iotpy.service file provided, changing the command to run iotpy according to your system.

# find where is your iotpy is installed 
which iotpy
# change permission
chmod u+x <path-to-iotpy>

# Edit this line of iotpy.service file
    ExecStart=<path-to-iotpy>/iotpy --dir <path-to-devices> --port 8085

# Save file into systemd directory
sudo cp daemonize/iotpy.service  /etc/systemd/system/.

# Start service 
sudo systemctl start iotpy

Now you can use commands like systemctl stop, to stop the service, and systemctl enable to enable the service to self-start at startup.

Powered by

Many thanks to:

  • Twisted
  • Milligram.css
  • Prometheus

And to the University of Zurich for support to this project.

About

Framework to expose IOT devices trough REST API and prometheus metrics

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published