Jump to content

Welcome to Smart Home Forum by FIBARO

Dear Guest,

 

as you can notice parts of Smart Home Forum by FIBARO is not available for you. You have to register in order to view all content and post in our community. Don't worry! Registration is a simple free process that requires minimal information for you to sign up. Become a part of of Smart Home Forum by FIBARO by creating an account.

 

As a member you can:

  •     Start new topics and reply to others
  •     Follow topics and users to get email updates
  •     Get your own profile page and make new friends
  •     Send personal messages
  •     ... and learn a lot about our system!

 

Regards,

Smart Home Forum by FIBARO Team


  • 0

help with net.HTTPClient()


JcBorgs

Question

Any experts on the net.HTTPClient() coding in here?

 

Am trying to build a QA for my car charger (Charge Amps HALO) and have access to the REST API. They have a bit different implementation to what I have worked with before, you need to login with email, password & APIkey to get a ”token” that you then use in other request. If I do this login on their swagger page I am able to get a token and then build a simple function to pull out information about my Charger, and this works just fine:

 

Code:

function QuickApp:GetData()
  http = net.HTTPClient()
    local url = "

Please login or register to see this link.

d"
    local requestBody = '

Please login or register to see this link.

d'
    local token 
="aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz"
 
    http:request(url, 
          {
            options = {
                data = requestBody, 
                method = "GET",
                headers = {
                           ["accept"] = "application/json"
                           ["Authorization"] = "Bearer " ..token
                           }
                       },
         success = function(response) 
                      print("response status: " ..response.status)
                      print("Response data: " ..response.data)
                    end
            })
end

Request URL from the Charge Amps swagger page>

Please login or register to see this code.

Curl from the Charge Amps swagger page>

Please login or register to see this code.

 

200

Response body from the Charge Amps swagger page>

Please login or register to see this code.

 

Log output in Fibaro HC3>

[21.04.2022] [18:34:25] [DEBUG] [QUICKAPP977]: response status: 200
[21.04.2022] [18:34:25] [DEBUG] [QUICKAPP977]: Response data: [{"id":"XXXXXXXXXXXXXXX","name":"XXXXXXXXXXXX","password":"XXXXXXXXXX","type":"HALO","isLoadbalanced":true,"firmwareVersion":"72","hardwareVersion":"2","ocppVersion":null,"settings":null,"connectors":[{"chargePointId":"XXXXXXXXXX","connectorId":1,"type":"Charger","settings":null},{"chargePointId":"XXXXXXXXXXX","connectorId":2,"type":"Schuko","settings":null}]}]
 
So the above part are working just fine, sensitive information have above been replaced with bogus information. But the issue I have is that I want to do another ‘function’ that handles the login to get a token (there is a login “swagger”on the Charge Amps swagger page) that can be stored in the HC3 as a variable, the  “tokens" are only valid for 2 hours and need to be regenerated several times each day to keep the QA working.
 
To be able to do this you need to provide apiKey, email & password, but I can’t get that to work….. Doing it on the Charge Amps swagger page works just fine, but need this in a ‘function’ in the QA to be able to automate the collection of ‘token’ :

Curl from the Charge Amps swagger page>

Please login or register to see this code.

Request URL from the Charge Amps swagger page>

Please login or register to see this code.

Response body from the Charge Amps swagger page>

Please login or register to see this code.

Code I have tried:

function QuickApp:CAlogin()
 http = net.HTTPClient()
 local requestBody = 'https://eapi.charge.space/api/v4/chargepoints/owned'
 local APIkey = "xxzzyyxxzzyyxxzzyy=="
 
http:request("https://eapi.charge.space/api/v4/auth/[email protected]&password=aabbccddeeff",{
    options = {
               data = requestBody, 
               method = "POST",
               headers = {
                          ["Content-Type"] = "application/json",
                          ["accept"] = "*/*",
                          ["apiKey"] = APIkey
                          }
              },
              success = function(response) 
                        print("Status", response.status)
                        print("Data", response.data)
                        end,
              error = function(message)
                      print("error:", message)
                      end
                }) 
end
 
This simply doesn’t  work and just gives a 400 as status code in the Fibaro log. But how do I do a net.HTTPClient() request that includes apiKey, email and password as required by Charge Amps? Tried to put email and password in the URL but that does not seem to work. Have also tried to put it in other parts of the code but it simply doesn’t work, always gives me a 400 status code.
Edited by JcBorgs
Link to comment
Share on other sites

Recommended Posts

  • 0

Try this

 

Please login or register to see this code.

 

Edited by jgab
Link to comment
Share on other sites

  • 0
  • Inquirer
  • 12 hours ago, jgab said:

    Try this

     

    Please login or register to see this code.

     

     

     

    @jgab

    Did a typo at first and it didn’t work at all…. just gave the 400 code again..

     

    But corrected this and now work as it should!

     

    Thank you!!!

    Edited by JcBorgs
    Link to comment
    Share on other sites

    • 0

    you might try to urlencode everything starting with ?,

     

    or send the data without json.ecode, like 
     

    Please login or register to see this code.

     

     

    Link to comment
    Share on other sites

    • 0
  • Inquirer
  • Got it working with tip from @jgab

     

    Now I just need to figure out how to store the token part of the data received into an variable, not an coding expert so tips are highly welcome..

    Link to comment
    Share on other sites

    • 0

    I don't think you should store the token in a QA variable.

    I believe that the structure could be something like this

    Please login or register to see this code.

     

    A more complex logic would renew the token first when you get an expired token error back from a request.

    I assume that getting a new token using the refreshToken is different from the initial log in procedure.

    Link to comment
    Share on other sites

    • 0
  • Inquirer
  • @jgab Amazing quick work, and with such high quality! You brought up several good solutions that makes the QA so much better.

     

    Have verified everything and it works just perfect, added code for the renewToken part and tested with a “button”, all works without any issues. Did change the names of a few local variables to limit confusions.

     

    Did like the idea to split code in cmd/button, but unfortunately in the ChargeAmps implementation there are different “headers” variables for different command so don’t think this will work in the end. But a question regarding the ‘cmd’ part, obvious what the method and path are for but what are the intention with the ‘cont’ and how should that be used?

     

    You gave me such a good help and an excellent ground to build upon. Will be adding some more buttons and labels and build upon what you provided to make a QA to handle the Charge Amps charger with. Also in the process of building scenes that combines functions/data from the Tibber QA and the ChargeAmps QA with the intention to charge the car when the energy cost are as low as possible.   

     

    Please login or register to see this code.

     

    Link to comment
    Share on other sites

    • 0

    The idea with cmd is of course to have a tailor made http function that makes it easy to talk to the api. It becomes a bit like http:request but more dedicated....

    The advantage is that the code should be smaller, collecting common http code in one place. The drawback is that it requires many optional arguments as the http requests are a bit different (ex. headers).

    So I made another proposal for :cmd that makes additional/optional parameters easier to handle. See below.

     

    In Lua you can send a table as argument to a function

    Please login or register to see this code.

    That can also be written as

    Please login or register to see this code.

    i.e. without the surrounding ().

    The function foo is defined with one parameter

    Please login or register to see this code.

    and args is bound to the whole table passed to foo.

    The reason for allowing this syntax is that we can have "named parameters", and the parameters can be passed in any order (as key-values in a table don't have an order).

    We can also check if a value is present and if not provide a default value if we want.

     

    Making self:cmd of that type we can make it a generalised cmd for all the api calls.

     

    The 'cont' parameter is a function that is called with the resulting data. It's a bit like the success function in a http:request. In the QuickApp:button1 it just prints the result. In login/refresh it updates the token variables.

    In the new version it's called 'response' and should be a function that takes an argument that is the json.decoded response

     

    Please login or register to see this code.

     

     

     

     

     

     

     

    Edited by jgab
    Link to comment
    Share on other sites

    • 0
  • Inquirer
  • @jgab 

    Will dig into your updates shortly…

     

    But have one thing that gets me into trouble>

    The response body from the “login” starts like this:

    Please login or register to see this code.

    And it is easy to assign variables data from the response like tokenCA =data.token

     

    But in the chargepoints owned respons body starts like this:

    Please login or register to see this code.

     

    And when trying to assign variables data from the response like CAid = data.id the CAid just ends up empty.

     

    Do understand that something is needed to be added to the data.id to get ”deeper” into the data, but what?

     

    And also if I as an example like to get “type” from the second connectorId I can’t just do data.connectors.type, how to specify which of the to “type” fields I will get?

    Link to comment
    Share on other sites

    • 0
    8 minutes ago, JcBorgs said:

    @jgab 

    Will dig into your updates shortly…

     

    But have one thing that gets me into trouble>

    The response body from the “login” starts like this:

    Please login or register to see this code.

    And it is easy to assign variables data from the response like tokenCA =data.token

     

    But in the chargepoints owned respons body starts like this:

    Please login or register to see this code.

     

    And when trying to assign variables data from the response like CAid = data.id the CAid just ends up empty.

     

    Do understand that something is needed to be added to the data.id to get ”deeper” into the data, but what?

     

    And also if I as an example like to get “type” from the second connectorId I can’t just do data.connectors.type, how to specify which of the to “type” fields I will get?

     

    So the result is an array of key-value tables.

    To use the first item (can there be more then one? Maybe if you have multiple accounts/chargers?)

    Please login or register to see this code.

     

    also the .connectors field is an array, to get the first do

    Please login or register to see this code.

    Here I don't know if they are always sorted on connectorId or if you need to search for the id you need.

    Edited by jgab
    • Thanks 1
    Link to comment
    Share on other sites

    • 0
  • Inquirer
  • @jgab 

    The new version crashes for some reason:

     

    Log output:

    [22.04.2022] [12:10:06] [DEBUG] [QUICKAPP978]: Charge Amps HALO 978

    [22.04.2022] [12:10:06] [DEBUG] [QUICKAPP978]: Calling /v4/auth/login

    [22.04.2022] [12:10:06] [DEBUG] [QUICKAPP978]: Status /v4/auth/login - 404

    [22.04.2022] [12:10:06] [ERROR] [QUICKAPP978]: QuickApp crashed

    [22.04.2022] [12:10:06] [ERROR] [QUICKAPP978]: main.lua:69: attempt to index a nil value (local 'data')

     

    Line 69:

          tokenCA = data.token
     
    Also realized one thing, in almost all other available commands the “id” from the ‘charge points owned’ are needed as a variable. So will implement that during the login the QuickApp:button1() is called and populates a variable just as token and refreshToken are being done in the Login. 

     

    Link to comment
    Share on other sites

    • 0

    Sorry, I'm flying a bit blind here....

    In :cmd it should not be a trailing slash in the url. It should be 

    Please login or register to see this code.

    (I changed in code above too).

    The reason is that you want path argument to start with a slash, like "/v4/chargepoints/owned" - just because that's how it is usually specified.

     

    Anyway, this brings up the check for errors. It seems like a wrong url still ends up as a success (response call) - so you probably need to check if the status is < 206 to treat it as a success. Do that in :cmd.

    Ex.

    Please login or register to see this code.

     

    Edited by jgab
    Link to comment
    Share on other sites

    • 0
  • Inquirer
  • @jgab

     

    Works just fine now!

     

    Your updated code is probably the best way to do it, but for someone that doesn’t possess your coding skill it starts to look really complicated ? and when/if something goes wrong it would be hard for me to find where the problem is….

     

    Will probably revert back to something like the original code you suggested, then add all the features, buttons and functions I want in the QA, will most likely be a really long code. When that is completed and I have full understanding how it work I will start to include your new and more smart methods. I need to learn more, start simple and then enhance over time.

     

    Thank you very much for all your effort and all of the detailed explanation, have learned so much from this!

    • Like 1
    Link to comment
    Share on other sites

    • 0
  • Inquirer
  • @jgab

    Spent some time on this over the weekend, managed to get a fully operational QA and then did an effort in trying to learn the method your code was built in and eventually managed to understand it and implemented it on the code I hade done. It actually reduced the number of code line from a bit over 500 down to less then 300. 

     

    My code is probably far from optimal but at least it is working and now have a fully functioning Charge Amps QA:

     

    Please login or register to see this attachment.

     

    Please login or register to see this code.

     

     

     

     

    Edited by JcBorgs
    Minor updates
    • Like 2
    Link to comment
    Share on other sites

    • 0

    Hi, great with this code, I see you have not published the QA in MarketPlace, are you planning to do so?  or can you share QA in other channel?  Håkan

    Link to comment
    Share on other sites

    • 0
  • Inquirer
  • @Håkan Enhager

     

    No I have not publish it, actually it has expanded a lot since I now also have included a “Smart Charging” function in the QA that works together with the Tibber Monitor QA to find the 4 cheapest hours to charge the car.

     

    Have some minor cleanup work to do and then it will be published.

    Link to comment
    Share on other sites

    • 0
  • Inquirer
  • 11 hours ago, Håkan Enhager said:

    Hi, great with this code, I see you have not published the QA in MarketPlace, are you planning to do so?  or can you share QA in other channel?  Håkan

    @Håkan Enhager
    Attached to this post is a scaled down version of the ChargeAmps QA without the SmartCharge functions (that requires Tibber Monitor QA)
     

    To be able to use this QA you need a Charge Amps API Key, you can request that by contacting Charge Amps support [email protected].

     

    You will need to put in your Charge Amps username, password and API key in the variables in this QA

     

    If you also have Tibber and uses the Tibber Monitor QA I can provide the current version of the full Charge Amps QA which also has a smart charging feature that works together with the Tibber Monitor QA and finds the cheapest slot of 1-10 hours (configurable how many hours you want). The Tibber Monitor QA has 11 hours that we can use to calculate the best time to charge the car, I do the calculation at 20:00 and always has a fully charged car in the morning at the lowest cost.

     

    Please login or register to see this attachment.

    Link to comment
    Share on other sites

    • 0

    Hi, thanks a lot. I am running tibber monitor as well, would be extremely helpful also with the other QA! Just sent a request to CA asking for the key as well.

    Thanks again and have a nice day

    Link to comment
    Share on other sites

    • 0
  • Inquirer
  • @Håkan Enhager

     

    Attached is the current version of the Charge Amps QA with the smart charge function.

     

    The principle is that every day at 20:05 it finds the cheapest block of 4 hours during the coming 11 hours and then automatically starts and stop the charger.

     

    The time when it does the calculation can be changed with buttons in the QA and the amount of hours can also be changed with buttons in the QA.

     

    It might not be perfect but has been working good for me the last couple of month.

     

    If you what to use this version, the other version without smart charge should be removed from your HC3.

     

     

     

    Please login or register to see this attachment.

    Link to comment
    Share on other sites

    • 0

    Very nice, thank you very much! Now just waiting for the API KEY from ChargeAmp!   Next weeks challenge will be to  find a good 24V Thermostat for Floor heating (water)  that looks good!  But thats another topic...

    Link to comment
    Share on other sites

    • 0
  • Inquirer
  • 1 hour ago, Håkan Enhager said:

    Very nice, thank you very much! Now just waiting for the API KEY from ChargeAmp!   Next weeks challenge will be to  find a good 24V Thermostat for Floor heating (water)  that looks good!  But thats another topic...

    Your welcome, please reach out to me if something isn’t working in the QA.

     

    24V Thermostat for Floor heating… sorry cant help you there😆

    Link to comment
    Share on other sites

    Join the conversation

    You can post now and register later. If you have an account, sign in now to post with your account.

    Guest
    Answer this question...

    ×   Pasted as rich text.   Paste as plain text instead

      Only 75 emoji are allowed.

    ×   Your link has been automatically embedded.   Display as a link instead

    ×   Your previous content has been restored.   Clear editor

    ×   You cannot paste images directly. Upload or insert images from URL.

    ×
    ×
    • Create New...