Skip to main content

Murano Device Client is the primary library for communicating with the Exosite Murano Platform.

Project description

A library for quickly testing, evaluating and writing client software for Murano devices.

Supported features:

  • HTTPS Device API

  • MQTT Device API

  • TOKEN Auth

  • TLS Client Cert Auth

  • Command Line Interface (gdc --help)

Requirements

  • Python 2.7.9+, 3.4, 3.5, 3.6

  • paho.mqtt (>=1.3.1)

  • requests (>=2.13.0)

  • docopt (>=0.6.2)

  • six

Installation

Run the following command.

> pip install murano-client

HTTP CLI Examples

Timestamp

> gdc -H https://t41hp23nod8s00000.m2.exosite.io/ http timestamp
1527272454

Activate

> gdc -H https://t41hp23nod8s00000.m2.exosite.io/ -u myDeviceName-1 http activate
97eWgtm9Et5VxwuJT8NiOK7w27Ly2GS092oSxgpW

Write

> gdc -H https://t41hp23nod8s00000.m2.exosite.io/ -k 97eWgtm9Et5VxwuJT8NiOK7w27Ly2GS092oSxgpW http write data_in '{"some": "json data"}'
[204] No content

Record

> gdc -H https://t41hp23nod8s00000.m2.exosite.io/ -k 97eWgtm9Et5VxwuJT8NiOK7w27Ly2GS092oSxgpW http record $(date +%s) data_in '{"historical": "data"}'
[204] No content

Read

> gdc -H https://t41hp23nod8s00000.m2.exosite.io/ -k 97eWgtm9Et5VxwuJT8NiOK7w27Ly2GS092oSxgpW http read data_in
data_in={"historical": "data"}

Poll

> gdc  -H 'https://t41hp23nod8s00000.m2.exosite.io/' -k 97eWgtm9Et5VxwuJT8NiOK7w27Ly2GS092oSxgpW http poll config_io 3000
[304] Not modified
> gdc  -H 'https://t41hp23nod8s00000.m2.exosite.io/' -k 97eWgtm9Et5VxwuJT8NiOK7w27Ly2GS092oSxgpW http poll config_io 30000
[200] config_io={"some": "config data"}

Content

List Content

> gdc -H 'https://t41hp23nod8s00000.m2.exosite.io/' -k 97eWgtm9Et5VxwuJT8NiOK7w27Ly2GS092oSxgpW http content list
requests_check.v1.tar.gz
ota_bundle_test.v2.tar.gz
ota_bundle_test.v1.tar.gz
gwe.v1.5.RC68.tar.gz
gwe.v1.5.RC59.tar.gz
gwe.v1.5.RC58.tar.gz
gwe.v1.5.RC57.tar.gz

Get Content Info

> gdc -H 'https://t41hp23nod8s00000.m2.exosite.io/' -k 97eWgtm9Et5VxwuJT8NiOK7w27Ly2GS092oSxgpW http content info gwe.v1.5.RC68.tar.gz
application/gzip,691529,1513931066,

Download Content

> gdc -H 'https://t41hp23nod8s00000.m2.exosite.io/' -k 97eWgtm9Et5VxwuJT8NiOK7w27Ly2GS092oSxgpW http content download gwe.v1.5.RC68.tar.gz
WARNING:urllib3.response:Received response with both Content-Length and Transfer-Encoding set. This is expressly forbidden by RFC 7230 sec 3.3.2. Ignoring Content-Length and attempting to process response as Transfer-Encoding: chunked.
> file gwe.v1.5.RC68.tar.gz
gwe.v1.5.RC68.tar.gz: gzip compressed data, last modified: Fri Dec 22 08:24:23 2017, from Unix

MQTT CLI Examples

Activate

Activate a client with via MQTT.

> gdc -H t41hp23nod8s00000.m2.exosite.io -u cleanup-stuff mqtt activate
oihLldO3f53dqyJYDmiRCijVsf4eQJeUxFSBnEsk

Publish

Publish a single payload with MQTT.

> gdc -H t41hp23nod8s00000.m2.exosite.io -k oihLldO3f53dqyJYDmiRCijVsf4eQJeUxFSBnEsk mqtt publish \$resource/data_in "{\"time\": $(date +%s)}"
rc=0, mid=1: {"time": 1528214840}

Subscribe

Subscribe to a murano client.

NOTE: MQTT Subscribe works on all resources of a Murano client. Subscribing to a specific resource is not supported. Unsubscribe is also not supported.

> gdc -H t41hp23nod8s00000.m2.exosite.io -k oihLldO3f53dqyJYDmiRCijVsf4eQJeUxFSBnEsk mqtt subscribe
update_interval.1528215003884000=60

Pubsub

Use this command to publish newline-delineated date to a client resource while simultaneously subscribing to its resources.

> while true
do
    echo "{\"time\": $(date +%s)}"
    sleep 0.5
done | gdc -H t41hp23nod8s00000.m2.exosite.io \
           -k oihLldO3f53dqyJYDmiRCijVsf4eQJeUxFSBnEsk \
           mqtt pubsub \
           \$resource/config_io
update_interval.1528215003884000=60

Client Applications

For examples of how to import this library, see the commands in the murano_client/commands/ directory.

Simple HTTP Example Application

#!/usr/bin/env python

# example.py

import time
import uuid
import json
from murano_client.http import MuranoHTTP, Http_ReadWriteCodes

HTTP_TIMEOUT = 5*60*1000 # 5 minutes
config_io = None

client_params = {
    "murano_host": "https://t41hp23nod8s00000.m2.exosite.io/",
    "murano_id": str(uuid.uuid4()),
    "http_timeout": 5.0,
    "debug": "DEBUG",
}

print("Client parameters: {}".format(json.dumps(client_params)))

hc = MuranoHTTP(**client_params)
hc.set_http_timeout(HTTP_TIMEOUT)

while not hc.is_activated():
    hc.http_activate()
    print("TOKEN: {}".format(hc.murano_token()))
    if not hc.is_activated():
        time.sleep(HTTP_TIMEOUT)

print("Starting long poll...")

while True:
    response_handler = hc.http_long_poll(
            'config_io',
            HTTP_TIMEOUT,
            time.time()
        )

    if response_handler.code == Http_ReadWriteCodes.NotModified:
        print("no config_io yet...")
    elif response_handler.code == Http_ReadWriteCodes.OK:
        print(response_handler.body)
        config_io = json.loads(response_handler.body.strip("config_io="))
        print("got config_io: {}".format(config_io))
        hc.http_write('config_io', "ACK")
    else:
        print(response_handler)

    if config_io:
        print(hc.http_write('data_in', str(uuid.uuid4())))

Simple MQTT Example Application

#!/usr/bin/env python

# example.py
from __future__ import print_function
import time
import uuid
import json
from murano_client.mqtt import MuranoMQTT

client_params = {
    "murano_host": "t41hp23nod8s00000.m2.exosite.io",
    "murano_id": str(uuid.uuid4()),
    # "debug": "DEBUG",
}

print("Client parameters: {}".format(json.dumps(client_params)))

mc = MuranoMQTT(**client_params)
mc.start()

mc.Config_IO = None

print("Starting activation...")
if not mc.is_activated():
    mc.activate()
    print("TOKEN: {}".format(mc.murano_token()))

def on_message(cls, userdata, msg):
    """ Override default on_message function. """
    _, resource, timestamp = msg.topic.split('/')[0:3]
    print("{}.{}={}".format(resource, timestamp, msg.payload))
    if 'config_io' == resource:
        try:
            cls.Config_IO = json.loads(msg.payload.decode())
            print("New Config_IO: {}".format(cls.Config_IO))
        except ValueError:
            print("Invalid JSON: {}".format(msg.payload.decode()))
mc.on_message = on_message

print("Starting program...")

mc.start()

while True:

    if mc.Config_IO:
        rand_data = str(uuid.uuid4())
        rc, mid = mc.publish(
                             '$resource/data_in',
                             rand_data,
                             qos=0
                             )
        print("rc={}, mid={}, data={}"
              .format(rc, mid, rand_data))
    else:
        print("waiting for config_io object...")

    mc.loop()
    time.sleep(1)

Simple MuranoClient Client Applications

The MuranoClient class takes the following constructor parameters:

  • mqtt_host - If provided, the application will use the MQTT protocol to communicate with Murano.

  • http_host - If provided, the application will use the HTTP protocol to communicate with Murano.

  • murano_id - This is the device identifier (e.g. serial number, etc.).

  • watchlist - Provide a list of resources from which to be notified of when new data is available. NOTE: Currently only one resource is supported.

  • http_timeout - Specify the length of time in between Long Poll connections when using HTTP.

  • debug - Turn the logging up or down. Valid values are the string values DEBUG, INFO, WARNING, ERROR and CRITICAL.

The application, below, uses the MuranoClient class’s MQTT option to “echo” payloads from the config_io resource to the data_in resource.

#!/usr/bin/env python

import sys
import signal
import time
from murano_client.client import MuranoClient

c = MuranoClient(
    mqtt_host='t41hp23nod8s00000.m2.exosite.io',
    murano_id=sys.argv[1],
    watchlist=['config_io'],
    http_timeout=5*60,
    debug='DEBUG')

def stop(signal, frame):
    print("stopping")
    c.stop_all()
    sys.exit(0)

signal.signal(signal.SIGINT, stop)

c.client_activate()
c.start_client()

while True:
    data_from_murano = c.watch()
    if data_from_murano:
        c.tell(
            resource='data_in',
            timestamp=time.time(),
            payload=data_from_murano.payload
        )

The example below uses the HTTP option to periodically write the current time into the data_in resource.

IMPORTANT:

#!/usr/bin/env python

import sys
import signal
import time
from murano_client.client import MuranoClient

c = MuranoClient(
    http_host='https://t41hp23nod8s00000.m2.exosite.io/',
    murano_id=sys.argv[1],
    watchlist=['config_io'],
    http_timeout=5,
    debug='DEBUG'
)

def stop(signal, frame):
    c.stop_all()
    sys.exit(0)

signal.signal(signal.SIGINT, stop)

c.client_activate()
c.start_client()

while True:
    c.tell(
        resource='data_in',
        timestamp=time.time(),
        payload='chirp: {}'.format(time.time())
    )
    print(c.watch(timeout=1.0))

INI State File

Required:

  • murano_host

  • murano_id

  • watchlist - comma delineated list of Murano resources

Optional:

  • murano_port

  • debug

  • murano_token

Example INI files:

# device.ini
[device]
murano_host = t41hp23nod8s00000.m2.exosite.io
murano_id = 4321
murano_port = 443
watchlist = config_io
debug = DEBUG
murano_token = XaFfMaOvrGxJgWk2Iftgw1cplYuZeSsUoKlKn0lb
#!/usr/bin/env python

from murano_client.ini import Device

d = Device('device.ini')
d.client_activate()
d.start_client()
print(d.watch()) # now set a value in the watchlist

Test

To execute tests:

> pip install -U tox
> tox

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

murano_client-18.7.17.tar.gz (37.5 kB view hashes)

Uploaded Source

Built Distribution

murano_client-18.7.17-py2.py3-none-any.whl (47.0 kB view hashes)

Uploaded Python 2 Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page