Need your feedback on a new key-value piston input type in webCoRE


#1

There are many feature requests out there so I attempted to find a common thread that connects a number of them, a feature that could be developed as an important building block for other improvements. The best balance between difficulty of implementation and applicability to feature requests seemed to be a new input type that would allow building out a key => value mapping, I’ll refer to it as “KV Input” in this post.

I have some of this feature implemented but need to gather requirements to ensure that it is flexible enough for all the situations where we would need to use it. This will not be finished soon, but I want to gauge interest and flesh out additional requirements.

Preview

The KV input accepts any number of key and value pairs, currently it looks like this:

When evaluated this produces a data structure like the following:

{
    "time": 1523633104179, 
    "power": 5339.0, 
    "request_id": "something_2"
}

Applications of key-value input

This is a building block for several features; please reply if you think of any other places where this would be useful.

Setting the initial items in a list variable

  • Currently:
    • the initial value of a list variable cannot be set when defining that variable
    • requires one Set Variable statement in the piston for each index that needs to be set
  • With KV input:
    • set the initial value of a list variable in the define block as you can with other variables

Set Variable action with list variables

  • Currently:
    • Index field uses “magic” to determine whether the value you type is a string or a variable name, probably does not support expressions
    • Can only set one index at a time
    • No way to clear out the list
  • With KV input:
    • Index can be specified with the same type of field we use elsewhere, making it obvious that you can choose a variable or a text value and avoiding any potential conflict there
    • Could set multiple indexes in one Set Variable statement
    • Could add a toggle to specify whether the KV input should add to or clear and replace the
      list

Passing arguments to a piston

  • Currently:
    • variable list works fine but requires the calling piston to define and populate variable names identical to arguments expected by the callee
    • can get messy with complex pistons reusing the same variables or with multiple callees
  • With KV Input:
    • pass arguments by value or expression to avoid unnecessary variables

HTTP request body

  • Currently:
    • accepts a list of variables, variable name is used as the request parameter name
  • With KV input:
    • support for parameter names that are invalid as webCoRE variable names (e.g. if you try to name a variable $loc-coords you’ll get _loc_coords)
    • expressions and logic in the request statement rather than polluting the piston with variables and set variable statements
    • dynamic parameter names

Any changes to the request body should be approached in a way that does not preclude the ability to support a custom body (i.e. body as freeform text rather than key-value pairs).

HTTP request headers

  • Currently:
    • only the Authorization header can be set
    • variable input would not work to set others since most headers include the - character which is invalid in webCoRE variables (e.g. Content-Type)
  • With KV input:
    • could allow any headers to be set

Related input types

I expect any field that accepts KV input to offer a choice of three input types: Key-value mapping, Variables by name, and List variable.

Variables by name

webCoRE already has the “variables” operand that allows you to select multiple variables where the variable name is used as the key to map each variable value. That may be somewhat obsolete but I don’t think it needs to go away. It is easier to keep it around for backwards compatibility than to automatically migrate those to the KV input and in some cases it may be more convenient. I will probably rename it to “Variables by name” to better confer that it generates a mapping.

List variable

List variables, while a bit tough to work with currently, can represent the same data that could be added in a KV input. It should be possible to select a single list variable as an alternative to the KV input.

Related topics

KV input is a building block for solutions to the following:

Discussion Questions

  • Is this flexible enough? Sometimes I feel like we need support for deep objects (e.g. build a multi-level object for a JSON request) but a UI for that gets incredibly complicated. If it is (or can be) possible to make lists of lists that might be good enough.
  • Does the field UI convey the key/value association well enough? There did not seem to be enough space to put the key and value side-by-side.
  • Should the operand types (Value, Expression, Device, etc) for keys be restricted? For example, I think that anything requiring the value of [Energy meter : power] as a key would be strange… but I don’t know that we really need to prevent that. It could be less confusing to only show Value, Variable, Expression, and Argument especially since device values would still be available in expressions. Restrict the dropdown or no?

List variable question
webCoRE Update v0.3.105.20180628: improvements to web requests, reorder variables, collapse fuel streams
Help with JSON POST request
#2

A lot of this is over my head, and I have a hard time seeing where I would use it. But one weakness that I think this could address is the ability to make better JSON calls - specifically where there is a subvalue. Like the “params” value in this post:

Understanding this is building block functionality and might not actually solve that problem on its own…

milhouse


#3

Once I understood (thanks to your assistance) of how to enter the list variables in a single line array, most of my issue was solved. What I really wanted was a multi-dimensional array, but, now that you’ve shown me the way to use the single-line array methods SmartThings webCoRE doesn’t really require that due to the normally limited volume of data used.

With that said, if your KV input method can make the setting initial array variables easier, I’m happy.


#4

I am not sure if this is related… but I would love to be able to pass a string (short text) along with the number to my fuel streams… Right now, it automatically records the date & time, the canister, fuel stream name, and a number. It would be infinitely helpful if I could pass a string along with each “Write data point”

For example, in the pic below, 15 is actually ‘Overcast’, but there is no legend visible, so it relies on my memory of what each number means.

When hovering, I would like for it to display something like this:

temp

Here is a little snippet of code that I am using to draw this out:

(contains(wuCurrent,'Snow') ? '90' : 
(contains(wuCurrent,'Hail') ? '80' : 
(contains(wuCurrent,'Thunderstorm') ? '70' : 
(contains(wuCurrent,'Rain') ? '60' : 
(contains(wuCurrent,'Drizzle') ? '50' : 
(contains(wuCurrent,'Fog') ? '35' : 
(contains(wuCurrent,'Overcast') ? '15' : 
(contains(wuCurrent,'Mostly Cloudy') ? '10' : 
(contains(wuCurrent,'Cloud') ? '5' : '0')))))))))

#5

Definitely I think there is benefit to a key-value input type – particularly with web requests which can require headers beyond the one “Authorization” header that is set by default. I have several APIs I’d like to leverage, but without passing my API key I am unable to use them.


#6

I don’t have any additional use cases to add, but this would be very helpful for me!


#7

I believe this would help me in getting information on a specific call where there are numerous Request Headers and Body. At the moment, i can use Postman to get it but don’t have much luck using WC. This is the cURL code:

curl -X POST
https://api.onegov.nsw.gov.au/FuelPriceCheck/v1/fuel/prices/nearby
-H ‘Authorization: Bearer myAccessToken’
-H ‘Cache-Control: no-cache’
-H ‘Content-Type: application/x-www-form-urlencoded’
-H ‘Postman-Token: 3b1e4b26-0957-4519-9db9-75f50879ecf6’
-H ‘apikey: myAPIkey’
-H ‘requesttimestamp: 05/11/2018 3:30 PM’
-H ‘transactionid: 0001’
-d ‘fueltype=E10&latitude=-33.879605&longitude=151.155464&radius=2&sortby=price’

This is for a fuel price check.


#8

I would definitely like to add custom headers. I am currently unable to utilize a external API because of this.

Thank you.