AutoTools AutoTools Connectivity and JSON Read

Discussion in 'AutoApps' started by Fighting Pickles, Feb 20, 2017.

  1. Fighting Pickles

    Fighting Pickles New Member

    Joined:
    Sep 13, 2016
    Messages:
    6
    Likes Received:
    0
    Hi all,
    I think I need some tutoring. I'm trying to test if the current wifi connection is secure. My task works like this:

    ---------------
    A1: AutoTools Connectivity, Check Wifi Networks True
    A2: AutoTools Json Read, json = %atwifinetworks, fields = ssid(),capabilities()
    A3: Variable Set, %wifi_secure = no
    A4: Variable Set, %capabilities_ssid = 1
    A5: For %ssid(), %this_ssid
    A6: If %this_ssid matches %My_Wifi
    A7: Variable Set, %wifi_secure = yes
    <<if>>
    %capabilities(%capabilities_id) contains WAP or WAP2
    A8: Stop​
    A9: End If
    A10: Variable Add, %capabilities_id + 1​
    A11: End For
    ---------------

    The variable %My_Wifi is set to the ssid of the currently connected wifi network. This variable is set in a different task.

    Here's the rub: the json returned by AutoTools is constructed so that the object {wifis} is populated by an array, and each array element contains keyword pairings with information about an individual wifi network . Further, each element of the {wifis} array contains another array element, [capabilities]. This keyword contains the security protocols suppurted by the individual wifi network's router.

    So, the mapping to the keyword capabilities is wifis.capabilities, right?

    Well, it appears, sort of that's the correct mapping, for when I map to capabilities, the return values are a complete, comma-seperated list of all the wifi networks' capabilities.

    For example, if 20 networks are in range, wifis.capabilities might return 63 values for the keyword capabilities, and there is no way to group these capabilities by an individual ssid.

    To work around this issue, I have tried changing the separator to a ';'. That symbol only appears at the end of the complete list of capabilities.

    I tried mapping to the [capabilities] element using wifis.[capabilities()], wifis.capabilities[()] and wifis.capabilities([]). Those didn't work.

    I'm stumped. What should I be doing?


     
    Last edited: Feb 20, 2017
  2. Fighting Pickles

    Fighting Pickles New Member

    Joined:
    Sep 13, 2016
    Messages:
    6
    Likes Received:
    0
    Wait - I found another (and perhaps correct?) way of trying to access the contents of capabilities() within each array element of wifis:

    ----------
    AutoTools Json Read, field: wifis[0].capabilities()
    ----------

    This should return the values in the capabilites array of the first object in the array wifis. Right???

    Nope. I get nothing.
     
  3. Fighting Pickles

    Fighting Pickles New Member

    Joined:
    Sep 13, 2016
    Messages:
    6
    Likes Received:
    0
    I can't help myself. I have to make a features request, although it's really not a request for a feature but a request for structuring data.

    João, why not make this WAY easier by changing the json structure of %atwifinetworks?

    I understand why you structured the json %atwifinetworks the way you did. All the instances of keyword "ssid" are just objects of class wifi. It's good architecture. But, in this case, I think you can do better with bad architecture.

    The most important change is to get rid of the array within an array. It creates complexity without creating a lot of value. You can do that by using simple objects rather than an array object.

    Another way to say this is, get rid of the array attached to wifis and just use an object for each instance of wifi.

    Maybe the json structure could be approached this way:

    {
    "distanceMeters":"0.356",
    "ssid":"Bobby's Wifi",
    "trusted":"true",
    "level":-68,
    "bandwidth":"20"
    "capabilities":["WPA-PSK-CCMP+TKIP","WPA2-PSK-CCMP+TKIP","WPS","ESS"],
    "mac":"44:32:c6:f27:46:20",
    "frequency":2417,
    "numConnection":0,
    "seen":1487620430355,
    }

    Fundamentally, this structure is built around individual objects rather than a collection of objects.

    A few notes on the above...
    1. Always lead with the field you are sorting by. In this case, it's distance, so lead with that keyword.
    2. The next keyword, if it is not leading, is the one humans will most easily understand/use. In this case, that's ssid.
    3. What keyword is next most important? I'm not sure, but I like knowing if the ssid is trusted by my device, so I put the keyword "trusted" next.
    4. I'm not sure if "level" represents signal strength, but if so, I'd put this keyword next. I'd also rename "level" to "signal strength".
    5. Bandwidth is a great thing to know, just short of signal strength. I'd use this keyword next. However, the return values for wifi networks near me shows "bandwidth" as "20" for each object. I'm thinking that's a bug that should be fixed. If not, and 20 is always going to be the result, dump the keyword as useless clutter.
    6. Next is "seen". I assume the value "1487620430355" represents the number of seconds since the beginning of time (or Unix time). Good god, man! You've got to convert that to human readable time! (In fact, that could be an AutoTools feature.) Save my brain!
    From there, it doesn't seem to matter what order things go in. They are all of equal importance, at least to me.

    Some notes on the keyeords themselves.
    • I'm not sure why you chose to represent distance in centimeters, but the unit seems inappropriate. I don't want to know a network is 1346 cm away, right? I'd much rather know it's 13.5 meters away. The user can do the conversion in his/her head, but why make the user do that? I'm an American. I have a hard enough time with kilometers, but centimeters?!?
    • Use trusted vs untrusted. There's a whole logic thing about using the possitive condition rather than the negative, but really it's just easier to understand what trusted: "yes" means rather than untrusted: "no".
    • Again, if "level" represents "signal strength", use signal strength. Users know what that means, even the idiots like I am.
    João, you do great work, man. It's easy to sit here on the sidelines and pick on AutoTools... especially when my job used to be called Pick on Software X. But, I'm a user, and if I'm whining about something and willing to write you about it, you can bet there are 20 more users whining about it and not writing you about it.

    So I hope you'll take my suggestions in the spirit I offer them: trying to help the product be 5 cm better when it is a kilometer of great. ;)
     
    Last edited: Feb 21, 2017
  4. joaomgcd

    joaomgcd Administrator Staff Member

    Joined:
    Feb 3, 2015
    Messages:
    9,479
    Likes Received:
    806
    Haha thank you very much :D Love posts like this that want to help and do not criticise in a harmful way like many other people like to do.

    I can't tell you the amount of "hate" people have for stuff like this. Usually it goes something like "Why the F**** does this work like this?? Stupid developer just wants to make money!!!" and so on... :p

    So, just to clarify, in my head the correct way to do this (and by correct, I mean the way that's most "object-oriented" so to speak) is to first select just wifis() in a first step, which will return an array of JSON objects, then with a For do a loop for each of those JSON objects and for each one use another JSON Read action to read capabilities().

    This way you'll cleanly get the properties for each wifi inside the loop :)

    About the JSON structure "order", I'm really sorry but JSON fields do not have an "order" unless they're an array. JSON represents an object's properties, so it wouldn't make much sense to have a fixed order. For example, if you're describing a car, which do you always say first? The number of doors it has? Or the type of gas it consumes? It doesn't make sense because there's no inherent order to an object's properties :) That's why you read them out by name rather then by index. Hope this clarifies it!

    About the units the fields are in, I just used the units for each field as they are in the OS, so that explains that :D

    About the "seen" field, I don't know which format the user wants to use, so I just return it in time since epoch, and yes, there's an AutoTools Time action to format it in any way you want ;)

    Hope this helps and clarifies stuff! Thanks!
     
  5. Fighting Pickles

    Fighting Pickles New Member

    Joined:
    Sep 13, 2016
    Messages:
    6
    Likes Received:
    0
    Thanks, João. I understand.

    But, that leaves me the problem I started with: I would like to be able to examine the contents of wifis.capabilities() for each wifi network contained in %atwifinetworks.

    So, lets say %atwifinetworks contains wifis[theJoaoNetwork, PentsPenthouseWifi, and aNetworkOfChristophers]. (These are the wifi network's ssids, of course.) For each of network, I want to examine wifis.[ssid and capabilities()].

    Or, look at the same thing if it were written in SQL...

    SELECT ssid, capabilities
    FROM wifis
    GROUP BY ssid;

    Now, in the JSON Read action, I can write in Fields, wifis[1].capabilities(). This gets me all the capabilites of the first element in the array wifis(). But, since I need to examine this same information in the 2nd and 3rd elements of wifis (aka PentsPenthouseWifi and aNetworkOfChristophers), I'm not sure how to do that. I can't figure out how to assign a dynamic value to wifis[1].capabilities, where '1' becomes a variable, say a variable called %wifi_number. If I could use a variable, I could construct something like this:

    A1: JSON Read, Simple, ssid()
    A2: JSON Read, %atwifinetworks, JSON Root - %networks
    A3: Variable Split %networks, Spliter {
    A4: Variable Set %total_networks to %networks(#)
    A5: Variable Set %wifi_number to 0
    A6: If %total_networks > %wifi_number
    A7: JSON Read, wifis[%wifi_number].capabilities()
    A8: Variable Split, wifies_capabilities(), ',' as splitor.
    A9: For %wifies_capabilities(), %this_capability

    A10: If %this_capability contains WAP
    A10: Set Variable %Secure_Networks to ssid - %ssid(%network_number)
    A11: GOTO A6
    A12: End If
    A13: Variable Add %wifi_number + 1
    A14: GOTO Line A6​
    A15: End If

    See where I'm going here?
     
  6. joaomgcd

    joaomgcd Administrator Staff Member

    Joined:
    Feb 3, 2015
    Messages:
    9,479
    Likes Received:
    806
    Here :) this is what I meant:
    Code (Text):
    Test (106)
        A1: AutoTools Connectivity [ Configuration:Check Wifi Networks: true Timeout (Seconds):120 ]
        A2: AutoTools Json Read [ Configuration:Simple Mode: true
    Json: %atwifinetworks
    Fields: wifis()
    Separator: , Timeout (Seconds):60 ]
        A3: For [ Variable:%index Items:1:%wifis(#) ]
        A4: AutoTools Json Read [ Configuration:Simple Mode: true
    Json: %wifis(%index)
    Fields: ssid
    Separator: , Timeout (Seconds):60 ]
        A5: Flash [ Text:%ssid Long:Off ]
        A6: End For
     
    • select wifis()
    • loop through each one
    • read json for each one
    Let me know if this makes more sense! :)
     

Share This Page