10. Python NodeWire Library

The Python NodeWire library can be used to create python based nodes. Python nodes can control physical devices or appliances especially when deployed on embedded systems such as raspberry pi. They can also be used as virtual nodes to control software functions on a host computer.

To develop and run python nodes you need to install NodWire on your computer or device. You also need a NodeWire account.

10.1. Creating an account on the NodeWire Dashboard

Visit the dashboard and create a new account. Remember your account name and password as you will need it to run your node in the next step.

10.2. Installing NodeWire

Make sure python and pip are installed on your computer (or raspberry pi). Then run the following from your shell or command prompt:

$ pip install nodewire

Now you are good to go.

10.3. Hello World

The simplest node consists on an instance of the NodeWire class which specifies the node name and the user account that is used to connect to the NodeWire cloud. The NodeWire object implements the PlainTalk protocol.

from nodewire.NodeWire import NodeWire

if __name__ == '__main__':
  nw = NodeWire()
  nw.debug = True
  nw.run()

The following configuration file should be provided in the working directory:

[node]
name = pyNode
id = eqqy0w

[user]
account_name = ahmad@microscale.net
password = secret

[server]
address = localhost:5000

10.4. Processing Messages

In order to receive and process NodeWire messages, you can pass a callback function to the NodeWire class

from nodewire.NodeWire import NodeWire

val = 0
def myfunction(msg):
    global val
    if msg.Command == 'get' and msg.Port == 'val':
        nw.send(msg.Sender, 'portvalue', 'val', str(val))
    elif msg.Command == 'set' and msg.Port == 'val':
        val = msg.Value
        nw.send(msg.Sender, 'portvalue', 'val', str(val))
    elif msg.Command == 'get' and msg.Port == 'ports':
        nw.send(msg.Sender, 'ports', 'val')

if __name__ == '__main__':
    nw = NodeWire(process = myfunction)
    nw.debug = True
    nw.run()

Instead of handling messages yourself, you can use the control class to automatically handle the messages for you:

from nodewire.control import control

if __name__ == '__main__':
    ctrl = control(inputs = 'val')
    ctrl.nw.debug = True
    ctrl.nw.run()

This example creates a node with node with a port named ‘val’. You can checkout the node on the Dashboard using the auto layout menu.

Although, you can interact with it, this node doesn’t actually do anything useful.

Ports can be made to control physical devices if you run this on a raspberry pi or similar devices.

from nodewire.control import control
import os

class bright(object):
    def on_brightness(self, Sender, Value):
        os.system("/usr/local/Cellar/brightness/1.2/bin/brightness " + str(Value))

    def on_volume(self, Sender, Value):
        os.system('osascript -e "set volume output volume ' + str(Value * 100.0) + ' --100%"')

if __name__ == '__main__':
    ctrl = control(inputs = 'brightness volume', handler=bright())
    ctrl.nw.debug = True
    ctrl.nw.run()

Here’s another example:

from nodewire.control import control

class Handler():
    def __init__(self):
        self.auto = False
        self.times = 0

    def lost_power(self, node):
        if sco.mains == 0 and self.auto: sco.ignition = 1
        self.times += 1

    def on_auto_switched(self, sender, value):
        self.auto = value

    def get_service_required(self, Sender):
        return 1 if self.times > 10 else 0

def connected(node=None):
    global sco
    if node is None:
        ctrl.create_node('sco', got_it=connected)
    else:
        sco = node
        sco.on_mains = handler.lost_power

if __name__ == '__main__':
    handler = Handler()
    ctrl = control(inputs = 'auto_switch', outputs = 'service_required', handler=handler)
    ctrl.nw.on_connected = connected
    ctrl.nw.run()

The following example defines a computation loop, which can run concurrently with node:

from nodewire.control import control
import asyncio

class Handler():
    def __init__(self):
        self.auto = False
        self.times = 0

    def get_count(self, Sender):
        return self.times

    async def compute(self):
        while True:
            await asyncio.sleep(1)
            if ctrl.start == 1:
                self.times+=1
                ctrl.count = self.times

if __name__ == '__main__':
    handler = Handler()
    ctrl = control(inputs='start', outputs='count', handler=handler)
    ctrl.nw.run(handler.compute())