TheThingSystem / node-thing-client

A node.js module to interface with TheThingSystem steward, as a thing
MIT License
2 stars 4 forks source link

Perform by device id #8

Closed GuySawyer closed 10 years ago

GuySawyer commented 10 years ago

Good day

Using node-taas-client and node-thing-client, I am trying to carry out a perform message using deviceID to determine which device's perform function is activated.

The relevant section of code in thing-client is:

, '/api/v1/thing/perform':
                function() {
                  var task, taskID, response;

                  response = { path: '/api/v1/thing/report', requestID: message.requestID, tasks: {} };

                    for (taskID in message.tasks) if (message.tasks.hasOwnProperty(taskID)) {
                        task = message.tasks[taskID];

                    if (task.deviceID === 'device/4')
                    {
                        console.log("THAT WAS A GREAT SUCCESS:    " +task.parameter);

                        if (task.perform !== 'toggle') {        //Toggle is Light Switch specific
                          response.tasks[taskID] = { error: { permanent: true, diagnostic: 'invalid perform value' }};
                          continue;
                        }
                        if ((!task.parameter) || (task.parameter.length === 0)) {
                          response.tasks[taskID] = { error: { permanent: true, diagnostic: 'invalid parameter value' }};
                          continue;
                        }
                        if (task.testOnly) {
                          response.tasks[taskID] = { success: true };
                          continue;
                        }
                    }
                  }
                  thing.reply(response);
                }

The code that I am running from test3.js in taas-client looks like this:

console.log("Toggle Slave 1 Switch 1");
        steward.performDevice('4', 'toggle', 'switch toggled', function(message) {
            console.log(require('util').inspect(message, { depth: null }));
        });

And this uses this code from taas-client:

ClientAPI.prototype.performDevice = function(deviceID, perform, parameter, cb) {
  if (parseInt(deviceID, 10) <= 0) throw new Error('deviceID must be positive integer');

  return this._send({ path      : '/api/v1/device/perform/' + deviceID
                    , perform   : perform
                    , parameter : JSON.stringify(parameter || {})
                    }, cb, true);
};

Originally, the perform was setup to use "performActors" from taas-client. But I understand that function to be used to invoke a perform from all devices of a particular prototype ie: /device/light.

I have three light switches connected to my BBB, and I want to invoke performs for each one individually. I can't however figure out how to access the deviceID from the message that is received by thing-client.

I added the "if (task.deviceID === 'device/4')" statement in the thing-client code I provided above. That was how I thought the information might be made available, but I am definitely wrong. I read through the info on the TTS website as well, but it looks like only the "performActors" method is described.

Update: I realise now upon closer inspection that "task" only has three parameters > Perform, Parameter and TestOnly. So that IF statement would never have worked. Also, upon inspection of the "message" in thing-client, there is no deviceID information. Here is the "message" value:

{ path: '/api/v1/thing/perform',
  requestID: '44',
  tasks: 
   { '96551466': 
      { perform: 'toggle',
        parameter: '"switch toggled"',
        testOnly: false } } }

But seeing as the "performDevice" function requires a deviceID, but the deviceID is never sent to thing-client, I really don't know how to carry out perform functions based on deviceID.

I appreciate all your guys help Regards Guy

mrose17 commented 10 years ago

sorry for the delay in replying. the steward provides "whoami" values such as "device/3". the deviceID itself is "3". so you can call either listDevice or performDevice using that value as the first parameter. does that make sense?

GuySawyer commented 10 years ago

Yes, that side of the equation I understand. However when it comes to the thing-client receiving that perform message from the Steward, there is no deviceID information.

To clarify, I have modified the test.js file in node-thing-client to be able to interact with sensors and switches connected to the BBB. So test.js is receiving the perform message from the Steward, but without any deviceID information, I don't know how to code test.js to recognise which switch the preform message is meant for?

mrose17 commented 10 years ago

sorry, i completely misunderstood the context. here is the answer:

when your code sends a register request, e.g.,

    { path              : '/api/v1/thing/register'
    , requestID         : '4'
    , things            :
      { 't1'            :
        { devicetype    : '/device/A/B/C'
        , name          : '...'
    ...

it is saying that "t1" (which is just a string) is the "temporary identifier" it is using to register the thing. the response that comes back looks like this:

    { requestID         : '4'
    , things            :
      { 't1'            :
        { status        : 'success'
          thingID       : 'thingID1'
        }

        // other results, if any, go here...
      }
    }

the steward is saying that from now on, over this connection, it will use "thingID1" to refer to the thing that was temporarily identified as "t1".

the reason that a "temporary identifier" is necessary is that you may want to register more than one thing at a time, and there has to be a way to correlate the things being registered to what comes back.

if you look at all the API interactions which follow, there is either a "thingID" parameter (e.g., observe) or the thingID is used as a tag (e.g., update).

GuySawyer commented 10 years ago

Ok, I thought the thingID might be useful, but it seemed like a one time use for registration. But it makes sense now how I can use the thingID value to identify devices on the BBB, except I don't see where the thingID is used in the perform message.

So If a perform message came through from the Steward, how would I know that it was for: let's say lightSwitch1, if there is no thingID information contained within the perform message?

Update: After another look at the TTS webpage on the simple thing protocol, I realised that within the perform message, the "task" object should also have a thingID value along with the perform, parameter and testOnly values. However, the message that I am receiving from the steward only has the latter three.

{ path: '/api/v1/thing/perform',
  requestID: '47',
  tasks: 
   { '10588320': 
      { perform: 'toggle',
        parameter: '"switch toggled"',
        testOnly: false } } }

Should I be using an alternate perform function as opposed to "performDevice", or why is there no thingID value? The perform message being sent by test3.js in taas-client looks like this:

steward.performDevice('4', 'toggle', 'switch toggled', function(message) {
            console.log(require('util').inspect(message, { depth: null }));
        });
GuySawyer commented 10 years ago

Morning Mr. Rose. I was just wandering when you might be able to get back to me on this?

mrose17 commented 10 years ago

sorry for the delay. my goal is to reply tomorrow morning (in a few hours!)

mrose17 commented 10 years ago

hi. sorry for such a long delay in replying.there should be a thingID value in addition to the 'perform', "parameter, and 'testOnly'.

i think i fixed it. please get the latest and try it out!

with respect to the perform message in test3.js - keep in mind that the integer deviceIDs are mapped into thingID (and vice-versa) by the steward. there isn't any relationship between them.

does that help? sorry for the delay in replying

GuySawyer commented 10 years ago

Ok great. Are you sure you updated the repository? I reinstalled it, but it doesn't seem to have changed. How exactly do I perform an update on the "thing-client" as opposed to just reinstalling it.

Ok, so only the Steward is aware of a relationship between an integer deviceID and the temporary thingID. On the taas-client side, we deal with deviceID and on the thing-client side, we deal with thingID?

mrose17 commented 10 years ago

sorry, i wasn't clear in my email. i updated the steward, not this repository. so, i should have said:: "get the latest version of the steward and run that", e.g.,

    % cd steward
    % git pull
    % cd steward
    % npm install -l
    % sudo sh /etc/init.d/steward restart

sorry!

GuySawyer commented 10 years ago

I updated the Steward, and the thingID information is still not present.

mrose17 commented 10 years ago

you're right. that's odd. i'm looking into it now.

mrose17 commented 10 years ago

finally! i added test4.js to node-taas-client to test the perform and then started figuring out what was going on.

if you get the latest from the steward, it should work. if not, time for me to take a long nap....

this issue has taken 18 days too long to resolve. sorry!

GuySawyer commented 10 years ago

I've been trying to give it a shot, but I keep getting "undefined error: no visible stewards".

I normally get this once or twice before taas-client or thing-client runs, but not this persistently. Could you give me a few pointers as to how I should go about debugging this error?

mrose17 commented 10 years ago

just so i'm looking in the right place, are you running a script that's using ThingAPI or ClientAPI. sorry for lacking the clue.

GuySawyer commented 10 years ago

I am running client script that is using ClientAPI locally on the same BBB as the Steward. I am also running script using ThingAPI from a BBB on the same local network. Both are giving me the same "No stewards visible" error.

mrose17 commented 10 years ago

it may be an issue with the mdns driver on linux. i'm going to test with a BBB. do you try the test immediately after starting the steward, or do you wait a few seconds?

mrose17 commented 10 years ago

well, i brought up a new steward on a bbb and run test3.js from node-taas-client, and it immediately found the steward and went to work.

so, there must be a timing issue involved. how long do you wait between starting the steward and starting one of your client/thing programs? thanks!

GuySawyer commented 10 years ago

I wait at least a minute or two. I tried to replicate your setup this time. Here is what I did.

ssh into BBB running steward. Kill steward and run again with console:

debian@steward:~$ cd steward/steward
debian@steward:~/steward/steward$ sudo sh /etc/init.d/steward stop
[sudo] password for debian: 
Stop steward services...killing 2110
debian@steward:~/steward/steward$ sudo sh -c ./run.sh

Here is the console output:

info: running on Linux Debian 7.2 ( 3.8.13-bone30 armv7l)
info: using node v0.10.22
info: [devices] loading climate driver
debug: [climate] begin
info: [devices] loading gateway driver
info: [devices] loading indicator driver
info: [devices] loading lighting driver
info: [devices] loading media driver
debug: [media] begin
info: [devices] loading motive driver
debug: [motive] begin
info: [devices] loading presence driver
info: [devices] loading sensor driver
info: [devices] loading switch driver
info: [devices] loading wearable driver
debug: [wearable] begin
info: [climate] loading ecobee-control driver
info: [climate] loading flower-power-sensor driver
info: [climate] loading insteon-control driver
info: [climate] loading koubachi-sensor driver
info: [climate] loading nest-control driver
info: [climate] loading netatmo-sensor driver
info: [climate] loading oregon-scientific-sensor driver
info: [climate] loading plantlink-sensor driver
info: [climate] loading samsung-control driver
info: [climate] loading teldus-meteo driver
info: [climate] loading wink-control driver
info: [climate] loading yoctopuce-meteo driver
info: [discovery] SSDP listening on http://0.0.0.0:1900
info: [gateway] loading automatic-cloud gateway
info: [gateway] loading ecobee-cloud gateway
info: [devices] failing ecobee-cloud gateway (continuing) diagnostic=Cannot find module 'ecobee-api'
info: [gateway] loading flower-power-cloud gateway
info: [gateway] loading insteon-automategreen gateway
info: [gateway] loading koubachi-cloud gateway
info: [gateway] loading lockitron-cloud gateway
info: [gateway] loading nest-cloud gateway
info: [gateway] loading netatmo-cloud gateway
info: [gateway] loading openzwave-usb gateway
info: [gateway] loading plantlink-cloud gateway
info: [gateway] loading reelyactive-reel gateway
info: [gateway] loading rfxcom-usb gateway
info: [gateway] loading telldus-live-cloud gateway
info: [gateway] loading tesla-cloud gateway
info: [gateway] loading wink-cloud gateway
info: [gateway] loading yoctopuce-hub gateway
info: [gateway] loading zigbee-xstick gateway
info: [indicator] loading cassandra-nosql driver
info: [indicator] loading dweetio-sensor driver
info: [indicator] loading grovestreams-sensor driver
info: [indicator] loading instapush-text driver
info: [indicator] loading mqtt-text driver
info: [indicator] loading nma-text driver
info: [indicator] loading prowl-text driver
info: [indicator] loading pushover-text driver
info: [indicator] loading twitter-text driver
info: [indicator] loading wink-dial driver
info: [indicator] loading wink-nimbus driver
info: [indicator] loading xively-sensor driver
info: [lighting] loading blink1-led driver
info: [lighting] loading blinkstick-led driver
info: [lighting] loading heroicrobotics driver
info: [lighting] loading hue driver
info: [lighting] loading insteon-led driver
info: [lighting] loading lifx-bulb driver
info: [lighting] loading robosmart-led driver
info: [lighting] loading tabu-lumen driver
info: [lighting] loading tcpi-led driver
*** WARNING *** The program 'node' uses the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node>
*** WARNING *** The program 'node' called 'DNSServiceRegister()' which is not supported (or only supported partially) in the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node&f=DNSServiceRegister>
info: [lighting] loading yoctopuce-color driver
info: [lighting] loading yoctopuce-powercolor driver
info: [discovery] PixelPusher listening on udp://*:7331
info: [media] loading audio-sonos driver
info: [media] loading audio-upnp driver
info: [media] loading pioneer-receiver driver
info: [media] loading video-appletv driver
*** WARNING *** The program 'node' called 'DNSServiceRegister()' which is not supported (or only supported partially) in the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node&f=DNSServiceRegister>
info: [media] loading video-chromecast driver
info: [media] loading video-roku driver
info: [motive] loading automatic-vehicle driver
info: [motive] loading lockitron-lock driver
info: [motive] loading tesla-model-s driver
info: [presence] loading fob driver
info: [presence] loading mobile-mqtt driver
info: [presence] loading reelyactive-tag driver
info: [switch] loading insteon-dimmer driver
info: [switch] loading insteon-onoff driver
info: [switch] loading telldus-dimmer driver
info: [switch] loading telldus-onoff driver
info: [switch] loading wemo-onoff driver
info: [switch] loading wink-onoff driver
info: [switch] loading wink-pivot-power-genius driver
info: [switch] loading zwave-dimmer driver
info: [switch] loading zwave-onoff driver
info: [wearable] loading watch driver
info: [discovery] reelyactive-reel driver listening on  udp://*:7018
notice: [steward] start uuid=2f402f80-da50-11e1-9b23-9059af69c1e1
info: [server] listening on wss://*:8888
info: [server] listening on wss://*:8887
info: [server] redirecting from http://*:80 to https://*:8888
info: [server] unable to listen on http://*:80 diagnostic=listen EADDRINUSE
info: [server] loading console route
info: [server] loading manage route
info: [server] loading oneshot route
info: [server] loading root route
info: [server] loading ble discovery
info: [server] loading mac discovery
info: [server] loading owl discovery
info: [server] loading portscan discovery
info: [server] loading ssdp discovery
info: [server] loading tsrp discovery
info: [discovery] OWL driver listening on multicast udp://224.192.32.19:22600
info: [discovery] SSDP listening on http://192.168.2.101:1900
info: [discovery] TSRP listening on multicast udp://224.0.9.1:22601
info: [discovery] UPnP listening on http://192.168.2.101:8886
info: [discovery] BLE stateChange state=unsupported
no ttyO1_armhf.com
info: [sensor] loaded nest-smoke driver
info: [sensor] loading texas-instruments-sensortag driver
info: [sensor] loading wemo-motion driver
info: [sensor] loaded wink-spotter driver
info: [sensor] loaded yoctopuce-4-20mA-Rx driver
info: [sensor] loaded yoctopuce-co2 driver
info: [sensor] loaded yoctopuce-light driver
info: [sensor] loaded yoctopuce-voc driver
warning: [steward] place/1 Home event=getWeather, diagnostic=check in 563.751 seconds
info: [discovery] PORT starting scan
info: [discovery] PORT finished scan

At this point, I ssh'd into the BBB from another terminal and performed these commands to run test3.js:

debian@steward:~$ cd node_modules/taas-client
debian@steward:~/node_modules/taas-client$ sudo node test3.js
[sudo] password for debian: 
*** WARNING *** The program 'node' uses the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node>
*** WARNING *** The program 'node' called 'DNSServiceRegister()' which is not supported (or only supported partially) in the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node&f=DNSServiceRegister>
undefined error: no visible stewards

Still getting the same error. What I did notice though, I think this problem started after your update to the Steward in order to add the thingID information to the perform messages coming through to thing-client. Do you think this problem might have been created there?

mrose17 commented 10 years ago

hi. am traveling. hope to answer this weekend!

GuySawyer commented 10 years ago

No problem. Interestingly enough, it started working again. I was travelling with my setup until yesterday. Today I got back to my office, connected it all up (exactly as it was connected while I was travelling) and it just worked.

I do still get the "no visible steward" error every now and then, but I can't explain why it didn't function at all until today. I would still like to figure out what caused the problem.

So any information you need to help debug, just shoot.

Regards Guy

mrose17 commented 10 years ago

it's definitely a timing issue. i just need to spend some time studying it... most likely today!

mrose17 commented 10 years ago

ok. i think i've figured it out. if it happens again, please let me know. thanks!

GuySawyer commented 10 years ago

Ok, it still does it every now and then.

Say I run taas-client to do some testing. Then cntrl-C to end it. Make some changes to the code and then run it again. Sometimes, it will give me the "no visible stewards" error, but not very often.

At some point, I want the taas-client and the thing-client to be able to recover from a failure (so basically try to start itself up again). So I think I need to get this issue smoothed out.

I have also had a chance to test the perform message for the thingID value that should be sent to the thing-client. The thingID value is still not present in the message? I have fully updated the Steward.

Thanks

mrose17 commented 10 years ago

hmmm... the string "no visible client" is no longer in either node-taas-client or node-thing-client... and i'm pretty sure that the thingID is being sent:

    >>> send: {"path":"/api/v1/thing/hello/11","response":"257245","requestID":1}
    >>> recv: {"requestID":"1","result":{"uuid":"2f402f80-da50-11e1-9b23-14109fe5a283:things","name":".things","comments":"simple thing protocol client","lastLogin":"2014-07-04T11:45:50.000Z","client":{"uuid":"2f402f80-da50-11e1-9b23-14109fe5a283:things","name":"testing1","comments":"","lastLogin":"2014-07-04T11:45:50.000Z","thingID":".things/11"},"success":true},"timestamp":1406136386}
    >>> send: {"path":"/api/v1/thing/prototype","things":{"/device/sensor/macguffin/sound":{"device":{"name":"All-Ears Noise Detector","maker":"Macguffin Industries, Ltd."},"observe":["motion"],"perform":["speak"],"name":true,"status":["quiet","noisy"],"properties":{"noise":"db","threshold":"db"},"validate":{"observe":true,"perform":true}}},"requestID":2}
    >>> recv: {"requestID":"2","things":{"/device/sensor/macguffin/sound":{"success":true}}}
    >>> send: {"path":"/api/v1/thing/register","things":{"t1":{"devicetype":"/device/sensor/macguffin/sound","name":"Living Room noise sensor","status":"quiet","device":{"name":"All-Ears Noise Detector","maker":"Macguffin Industries, Ltd.","unit":{"serial":"...","udn":"5eb160e4-e770-4e97-b8ef-dd89aa0a80ed"}},"updated":1406136385284,"info":{"noise":20,"threshold":35}}},"requestID":3}
    >>> recv: {"requestID":"3","things":{"t1":{"success":true,"thingID":"99702045"}}}
    { requestID: '3',
      things: { t1: { success: true, thingID: '99702045' } } }
    >>> getToWork: thingID=99702045
    >>> recv: {"path":"/api/v1/thing/perform","requestID":"1","tasks":{"47793869":{"thingID":"99702045","perform":"speak","parameter":"\"hello world\"","testOnly":false}}}
    { path: '/api/v1/thing/perform',
      requestID: '1',
      tasks:
       { '47793869':
          { thingID: '99702045',
            perform: 'speak',
            parameter: '"hello world"',
            testOnly: false } } }
    >>> speaking: "hello world"
    >>> send: {"path":"/api/v1/thing/report","requestID":"1","tasks":{}}
    >>> send: {"path":"/api/v1/thing/update","things":{"99702045":{"status":"noisy","updated":1406136415577,"info":{"noise":37,"threshold":35}}},"requestID":4}
    >>> recv: {"requestID":"4","things":{"99702045":{"success":true}}}
GuySawyer commented 10 years ago

Do I need to update node-thing-client as well? I only updated the Steward.

Are you using the thing-client test file to get those results?

I will try with the test file, and updating thing-client tomorrow, if I don't get your suggestions before then.

Thanks

mrose17 commented 10 years ago

that was running: the steward in one window, node-thing-client's test.js in a second window, and node-taws-client's test3.js in a third window... the latest versions of all... good luck!