Setup a webthing-python

I have trouble understanding how to implement a temperature sensor as webthing-python.
I have read the blog and the doc’s but i still do not see how…

this is my temperature, its stored as number to a file.

def getTemperature():
    temp = open('/tmp/sensors/temperature.1.temperature','r')
    print temp
    print temp.read() 

it gets printed like this:

root@espresso:/IoT/espresso# python coffeemachine-single.py 
<open file '/tmp/sensors/temperature.1.temperature', mode 'r' at 0x900f38>
25.23

2019-04-24 19:17:38,069 coffeemachine-single.py:56 INFO starting the server
2019-04-24 19:17:41,551 web.py:2162 INFO 200 GET / (192.168.178.56) 26.22ms
2019-04-24 19:17:41,612 web.py:2162 INFO 200 GET /properties/on (192.168.178.56) 12.09ms
2019-04-24 19:17:41,639 web.py:2162 INFO 200 GET /properties/TemperatureC (192.168.178.56) 12.55ms
2019-04-24 19:17:41,689 web.py:2162 INFO 101 GET / (192.168.178.56) 33.37ms

my code has another property:

def coffeemachine():
    thing = Thing('Coffeemachine',
                ['OnOffSwitch','Temperature'],
                'A web connected coffeemachine'
            )
    thing.add_property(
        Property(thing,
            'on',
            Value(True),
            metadata={
                '@type': 'OnOffProperty',
                'title': 'On/Off',
                'type': 'boolean',
                'description': 'Whether the coffeemachine is turned on',
            }
        )
    )
    thing.add_property(
        Property(thing,
            'TemperatureC',
            Value(getTemperature()),
            metadata={
                '@type': 'TemperatureProperty',
                'title': 'Temperature',
                'type': 'number',
                'description': 'The temperature of the heater (in Celsius) inside the coffeemachine.',
                'minimum': -20,
                'maximum': 100,
                'unit': 'celsius',
                'readOnly': True,
            }
        )
    )
    return thing

and i call the server as:

def run_server():
    thing = coffeemachine()

    # If adding more than one thing, use MultipleThings() with a name.
    # In the single thing case, the thing's name will be broadcast.
    server = WebThingServer(SingleThing(thing), port=8888)
    try:
        logging.info('starting the server')
        server.start()
    except KeyboardInterrupt:
        logging.info('stopping the server')
        server.stop()
        logging.info('done')


if __name__ == '__main__':
    logging.basicConfig(
        level=10,
        format="%(asctime)s %(filename)s:%(lineno)s %(levelname)s %(message)s"
    )
    run_server()

I do not see the value on my gateway when looking at the coffeemachine thing.
the full file is viewable here.

Works fine for me, after changing the following line:

['OnOffSwitch','Temperature'],

This should be:

['OnOffSwitch','TemperatureSensor'],

When adding your thing, you can select “Temperature Sensor” in the drop down, rather than “On/Off Switch”.

Hmm. That does not work for me. It changed the icon it shows when I select Temperature Sensor in the drop down, but the value stays 0.
Let me ask another thing regarding this same code. Maybe that sheds some light on what’s wrong.
I am on the view where I see my temperature and at the other side the on/off button.


if I click on the On/Off button the switch slides but my terminal does not show a new line and I do not get a new line in the log as well. Is that normal?

OK, i figured out why i didn’t get the temperature. I added a return to the getTemperature and another function to get the button value in the same way from a file. Nothing happens when i click the on/off.

I noticed the Action and Events are used in the samples but i don’t understand in what direction.

Are Actions where I define what happens when the On/Off button gets clicked in the gateway-webinterface and Events what happens when the webthing replies stuff?

like:
Action: Gateway -> Webthing
Events: Webthing -> Gateway

You need to pass a callback to the Value you create for the on/off prop. This will be called whenever the value is changed (from the in and outside iirc).

Edit: regarding actions and events, kind of, they’re like partial prop functionality, but also very much not. They’re separate concepts from properties and often complement them (looking at the actions/events in the schemas may help)

Exactly what im asking.
Where and how to implement the callback?
It wold help me to see this simple example of a lamp on/off like for arduino in python. Its a pitty that the sample implements a Fader but not the most basic on/off completly.
@mstegeman may you concider to add the callback of on/off in the example/single-webthing.py? Your example of py/Java/JS webthing inherits the play/pause buttons and that makes it tricky to understand for me…

The only experience with that (and python) I have would be this: https://github.com/freaktechnik/WebOfTXT/blob/master/main.py#L437-L444 (see also https://github.com/mozilla-iot/webthing-python/blob/master/webthing/value.py#L23 )

See this example for how to implement the callback. Note that you don’t have to use a lambda function there, you can pass in a normal function.

Concepts:

  • Properties are essentially individual stateful items, i.e. a switch value, a dimmer level, etc. They can be set and queried, nothing else. The callback to the Value is intended as a way to propagate the new value to the device itself, rather than just being held in a variable.
  • Actions are intended for triggering more complex routines that may or may not affect properties. For example, you could have an action that queues a whole list of songs for a music player. That is more complex than just setting a single property.
  • Events are asynchronous data that is pushed up from a device to the gateway/controller/whatever.

let me pic this up again.
I have a device that can be controlled from a frontswitch and i whant to implement a webthing switch additional. So there is a possibility that the webthing messes up the status of on/off.

How can i first check the status of the device and bring it in sync with Value() on startup?

thing.add_property(
        Property(thing,
            'Heater_On-Off',
            Value(True),
            metadata={
                '@type': 'OnOffProperty',
                'title': 'On/Off',
                'type': 'boolean',
                'description': 'Whether the coffeemachine is turned on or off',
            } 
        ) 

And how do i connect my switch function to take effect in the same place after determining the real status?

You should just check the proper status before creating the property.

I don‘t see how to proceed.
Value(true) is a class of webthing/Value.py and has a function get(self).
I think it‘s somehow possible to get the stored webthing status and compare it with a real device status before changeing the webthing status. But i need some more help here.

There is not a “stored status”. Your webthing is a standalone process, so unless you’re persisting the property value somewhere, you’re going to have to query the device directly to get the physical state.

The gateway caches property values while it’s running, but I’m not going to suggest pulling the value from the gateway.

Am I misunderstanding?

let’s say my device in on.
It somehow then looses wifi and i switch it off during that offline phase.
Then (i assume) the gateway will still think the device is on and my device and the switch differ in the state of on/off. (off will be the stat where my device is on)
Is this example easier to understand what i fear?

So the problem here is really that the property value on the gateway is wrong?

I don‘t know. That was a question.

Let me step in further up.

My IoT device does not only have a pysical state, it can change its state itself.

Maybe I misunderstand how the webthing works.
I thaught this is the Line to insert a change of the on/off state comming from the IoT device. But maybe its the status of the gateway representation. If so, i don’t understand where to get the change request comming from the gateway to my IoT device requesting to switch on/off…

Where do I have to INSERT changes comming from my IoT device to update the gateway and
where do I have to LISTEN to changes comming from the gateway requesting the IoT device to switch on/off?
can you link me the github Line?

The webthing itself knows nothing about the gateway. The webthing is a standalone entity.

You should take a look at a non-fake example.

When creating a property, this code first retrieves the physical state (i.e. the current value), and sets up a handler for when the property is changed by a client (using the self.set_volume method).

Then, in a background thread, the webthing is polling the current device state and updating the internal value (using self.update_volume).