API questions and issues

I’ve been using the info from http://docs-local.appbond.com/ to try to create a Windows application. I will be glad to provide you the application and source once I have completed it if you would like to distribute it

But I’m running into some issues. First when I attempt to issue an action that is returned from querying the device, so of them return a 400 invalid request. Then when I use a sniff to see what the Android app is doing rather than issuing the TurnOn / TurnOff action, is issues at commands//tx, and to be more confusing the hex number is not listed in the command listing, and is different for different devices. How should I be trying to issue these commands?

Also, I’d like to make this like the android app, where the first time you run it you give it your logon credentials and it retrieves the information on your bridge. Can you help me with how to do that?

What language / IDE are you using?

/// <summary>
/// Execute an action
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="devid"></param>
/// <param name="action">Action ID (string)</param>
/// <param name="data">Request data to pass to action</param>
/// <returns></returns>
public T ExecuteAction<T>(string devid, string action, Data data = null)
    where T : class, new()
{
    // Make sure the device id doesn't contain bridge id in front
    Debug.Assert(!devid.StartsWith(id));

    string command = $"/v2/devices/{devid}/actions/{action}";

    // In case it's in timer callback
    lock (timer_lock)
    {
        // Because we call GetStatus anyways - restart Timer after
        StartUpdateTimer(0);

        // Note: since it's using Method.PUT - there's no return value
        T ret = ExecuteAction<T>(command, data);

        if (bpup == null || !bpup.connected)
        {
            // so need to request state
            ret = GetDeviceState<T>(devid);
        }

        StartUpdateTimer();

        return ret;
    }
}

/// <summary>
/// Execute Action with Data
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="command">Full string, made in above ExecuteAction</param>
/// <param name="data"></param>
/// <returns></returns>
public T ExecuteAction<T>(string command, Data data = null)
    where T : class, new()
{
    _token_ = Token;

    if (data == null)
        data = new Data();

    // Note: since it's using Method.PUT - there's no return value
    T t = Execute<T>(command, data, method: Method.PUT);

    return t;
}

/// <summary>
/// Overwrite base Execute<T> to handle return error from Bridge
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="command"></param>
/// <param name="json"></param>
/// <param name="timeout"></param>
/// <param name="method"></param>
/// <param name="dontClearErr"></param>
/// <returns></returns>
public new T Execute<T>(string command,
                object json = null,
                int timeout = 0,
                Method method = Method.GET,
                bool dontClearErr = false)
    where T : new()
{
    T ret = base.Execute<T>(command, json, timeout, method, dontClearErr);

    DevicesResponse resp = ret as DevicesResponse;
    if(resp != null && resp.ContainsKey("_error_msg"))
    {
        string j = json != null ? JsonConvert.SerializeObject(json) : "";

        LogErr($"Command '{command}' {j}: '{resp["_error_msg"]}', Method {method}");
    }

    Thread.Sleep(ExecuteSleep);

    return ret;
}


/// <summary>
/// Json request body
/// </summary>
public class Data {}

/// <summary>
/// Data class for actions taking one int argument
/// </summary>
public class ActionDataInt : Data
{
    public ActionDataInt(int arg)
    {
        argument = arg;
    }

    public int argument { set; get; }
}


/// <summary>
/// Currently only device property which can be modified
/// </summary>
public class TrustStateData : Data
{
    public TrustStateData() : this(false)
    {
    }

    public TrustStateData(bool trust_state)
    {
        this.trust_state = trust_state;
    }
    public bool trust_state;
}

I’m using VB.Net, and what I’m doing is sending the HTTP messages described at http://docs-local.appbond.com/#section/Introduction/Contributing. Is there a DLL and a corresponding API? If so, where is that documented?

The two issues I have with the http method, is that I use v2/devices/{device_id} to get the device actions, but then when I use v2/devices/{device_id}/actions/{action_name} to execute the action, some of them work and some don’t. Using a packet sniffer I find that I need to send messages like v2/commands/763c2dee/tx where the hex string is different depending on the device and command.

The second issue, is that I would like to make this work like the android app (so that I could give it to you to distribute so Windows users would have a Bond Home like app), so I’d like to figure out how to use the user’s login credentials to get the Bond ID so I could then find the IP address. Right now the user would have to enter either the IP address or the Bond ID for the app to get the token.

First prize for me would definitely be an API I could use directly, but if not sending the HTTP messages isn’t a problem as long as I know how they work.

And when I get this done, I’d be glad to give it to you, including the source, so that you could provide it for your users.

Thanks

Dan

Dan - you don’t need to actually send the tx commands in any normal usage.
In fact, the Actions are built so the tx commands are no longer the preferred API method (as they were originally thr only options way back in the alpha days).

Yes, the Powered-by-Bond devices and Bridge do low-level revert to tx for actually sending commands, but the higher functioning Actions are preferred as the API endpoints. I converted all my tools and integrations to Actions some time ago.

I’d suggest we troubleshoot what Actions are not working and why.
Do you use and trust State?
If so, are you using a mixture of original non-Bond device remotes and the API / app / integrated voice assistants?

So, when I issue the command …v2/devices/

I get the result

{“name”:“Fan”,“type”:“CF”,“location”:“Family Room”,“actions”:[“SetSpeed”,“TurnLightOn”,“TurnOff”,“Stop”,“TogglePower”,“TurnOn”,“IncreaseSpeed”,“DecreaseSpeed”,“ToggleLight”,“TurnLightOff”],"":“ad0d508e”,“commands”:{"":“85b23199”},“state”:{"":“cba6d64b”},“properties”:{"":“ef2a76a9”},“skeds”:{"_":“4be3a050”}}

Which shows I have an action for TurnOff

But when I issue …v2/devices//actions/TurnOff I get a response of BadRequest (400). When I use the Bond android app for this device, I only see actions for Power Off (which isn’t listed in the actions above) and IncreaseSpeed, DecreaseSpeed (which are listed as Increase Speed and Decrease Speed, with spaces). The only actions that work are Stop, IncreaseSpeed, DecreaseSpeed and TottleLight.

So, there must be some other information about actions that I’m not getting.

Also, I still want to be able to get the bond bridge id from the user’s username/password so that I don’t have to have them enter it the first time they run the app.

I have tried using state, but it’s not accurate for all my fans. One of them returns the data correctly, but the other one shows the fan/light off even when it’s on.

Appreciate the help and hopefully you’ll see what I’m doing wrong.

This “Power Off” is a command, rather than an action. A command is just a name, an icon, an action, and maybe a signal to transmit. It’s just a way to tie a signal to an action and vice-versa, and present them in an app-friendly way. The action is TurnOff in this case. It’s a similar deal with “Increase Speed” etc.

There should be an error message in the body of this response, what does it say?

Where does it get the list of commands? Maybe that’s what I’m not doing correctly. Am I supposed to be doing a different call to get the commands?

The only error message is The remote server returned an error: (400) Bad Request.

This is a WebException when I do the getresponse.

You can get these from the commands subtree of a device’s API, instead of the actions subtree. This endpoint is similar to devices in that it’s just a bunch of IDs, which you then request to get info about each individual command. Bond Local API

I’m not sure why you’re seeing this, every 400 or 500 error should provide a bit of explanation in the response body.

I’m thinking that the problem is the lack of tracking for your current speed, because the device doesn’t know your fan’s maximum speed. If so, this is an old problem that I need to address. If it is this problem, I’d expect to see “action not supported” in the response body.

OK, this isn’t too clear from the doc, but I think what I need to do is ignore actions, get all the commands, then get the detail from each of them to use. So, I’ll do that and I think it might fix my problems (still not sure why some actions work and others don’t, …).

Any help on getting the bridge id from the username/password?

Getting closer. So I retrieve the numeric ID’s of all the commands, then for each command I get the details, saving away the action, then when I want to trigger it I send devices//actions/

This works for everything except the TurnOff action, which still returns a 404.

Is there something different about this action?

If you’re consulting the commands collection, I suggest you stick to using commands rather than switch to actions. You can transmit a command’s signal with Bond Local API. This would get you identical functionality to the app.

However, actions are what we designed for integrations to use. Your TurnOff action not working is almost certainly a bug. I’d like to diagnose it,

You previously said 400, can you confirm which one it is? As far as diagnosing this goes, they’re very different. If 404, there won’t be a response body. If 400, there will be a response body with an error description, whatever you’re using that results in

might be suppressing the response body? Can you try curl on this endpoint? (Bond Local API has an example)

Something like curl -H "BOND-Token: {your token}" -i http://192.100.0.61/v2/devices/{device id}/actions/TurnOff -X PUT -d "{}"

We focused on documenting our local API, our cloud API is undocumented and I don’t know when we plan to move to open it up. So this isn’t available yet.

Success, using the commands works perfectly. Do you want me to still chase down the 400/404 issue? I’ll be glad to help debug anything you want.

One comment, if you really want people to use this API, you might want to consider putting up a simple demo that shows exactly how to do it. The individual descriptions don’t really tell the story. I’d be glad to put together a simple VB.Net app if you would like.

Now the only thing I have to get figured out to make this work the way the Android app does, is figure out how to get the Bond ID (so I can get the IP address). The Android app gets it from the username/password. Is there a way I can do that.

After I get it all cleaned up (and think about how I’d like the UI to work) I’d be glad to provide you with the app and source code if you’d like to distribute a Windows app to your users.

BTW, is there anything useful I can do with actions?

Thanks for all your help.

First, thanks so much for all your help. Don’t think I would have figured it out all on my own.

Next, not sure if you’re the right guy to talk to about this, but I now have a fully functional Windows app. Not sure if you guys would be interested in it to distribute or not. I have to image there are people who would like to be to control the bond from their Windows machine. I’ll include some images, but I’ll be the first to admit that UI is not my strong suit, so if there are suggestions for how it should look, I’m open.

Anyway the main screen lists all the devices on the left. When you select a device it populates the right listbox with the available commands. Then if you click or double click an option (which is set as a preference) it executes that command.

image001.png

If you click on the Bridge menu item, you get:

There’s also a help screen and ability to generate a debug file which lists all the https commands sent, if there is a problem.

Anyway, if there’s any interest, let me know.

And as a last note, something that I can’t figure out how to do via the Android app (but I’m about to try putting in my app) is to delete a device. Is there a way in the Android app to do this?

Once again, thanks for all the help.

Dan

Well, I guess I see why the Android app doesn’t support this. When I tried using the DELETE command with v2/devices/ I get back a 405 Method Not Allowed. So, I’m guessing this isn’t implemented?

You DELETE an individual device: http://docs-local.appbond.com/#tag/Devices/paths/~1v2~1devices~1{device_id}/delete

In the Android app, you can find this in the device screen -> settings (top right) -> remove device (top right)

1 Like

OK, I was just calling it wrong. But I still don’t see it in the Android app (not that it matters to me anymore). When I bring up the app it shows me all the devices and the bridge, there’s a menu at the bottom left, but no remove device. Then I select the device I want to delete, there’s a menu at the top right, I go to settings and it displays a lot of stuff (status, name, location, bond id, …) but no entry for delete.

Once you go into settings on a specific device, hit the same menu button in top right again - the context has changed and now will show Remove Device:

OK, I see it now, but this is pretty hidden away (maybe on purpose?).

So, I’m using the command tx functionality to control things, which works fine. But I’d like to understand what actions are used for. At the moment I’m not doing anything with them, and even after reading the doc, I’m not sure what there purpose is.

Can you enlighten me?

Actions are the common API to control any Bond device. They’re used by pretty much every integration that I’m aware of, both our own or community-built.

Bond Bridge devices have Commands, which are signals tagged with what Action they represent and some presentational fields (name, icon, etc.)

Smart-by-Bond devices (smart ceiling fans, lighting, etc.) only have Actions.

So right now your app would not work for Smart-by-Bond devices.

Yes, please let me know if it’s a 404 or 400, and, if it’s a 400, what’s the response body?

1 Like